Package: release.debian.org
Severity: normal
User: release.debian.org@packages.debian.org
Usertags: unblock
Hi,
I'm considering an update to libdrm for wheezy, to get newer hw support
on radeon and intel. Upstream changed the libdrm_nouveau API/ABI in the
mean time, so this update would revert nouveau to the current state in
wheezy (2.4.33-3).
diff below comes from "git diff libdrm-2.4.33-3 | filterdiff -x
'*nouveau*' -x '*tests*' -x '*ChangeLog' -x '*exynos*'"
Excluded files:
- per the above, debian/patches/revert-nouveau-rewrite.diff means
nouveau doesn't actually change
- exynos is new in this release, but not built; it will be added in
jessie
- tests and changelog should be self-explanatory
Cheers,
Julien
b/.gitignore | 4
b/Makefile.am | 6
b/autogen.sh | 2
b/configure.ac | 88 ++-
b/debian/changelog | 29 +
b/debian/control | 2
b/debian/libdrm-dev.install | 1
b/debian/libdrm-intel1.symbols | 8
b/debian/libdrm-omap1.symbols | 4
b/debian/libdrm-radeon1.symbols | 2
b/debian/libdrm2.symbols | 5
b/debian/patches/series | 2
b/debian/rules | 16
b/include/drm/drm.h | 22
b/include/drm/drm_mode.h | 25
b/include/drm/i915_drm.h | 71 ++
b/intel/Makefile.am | 2
b/intel/intel_bufmgr.h | 24
b/intel/intel_bufmgr_gem.c | 364 +++++++++++-
b/intel/intel_bufmgr_priv.h | 5
b/intel/intel_chipset.h | 79 ++
b/intel/intel_decode.c | 106 +++
b/intel/test_decode.c | 2
b/libdrm_lists.h | 29 +
b/libkms/Makefile.am | 2
b/man/Makefile.am | 11
b/man/drmAvailable.man | 25
b/man/drmHandleEvent.man | 45 +
b/man/drmModeGetResources.man | 79 ++
b/omap/omap_drm.c | 199 ++++++
b/omap/omap_drm.h | 36 -
b/omap/omap_drmif.h | 4
b/radeon/Makefile.am | 2
b/radeon/r600_pci_ids.h | 83 ++
b/radeon/radeon_bo_gem.c | 48 +
b/radeon/radeon_bo_gem.h | 4
b/radeon/radeon_cs_gem.c | 2
b/radeon/radeon_surface.c | 460 ++++++++++++----
b/radeon/radeon_surface.h | 2
b/xf86drm.c | 31 +
b/xf86drm.h | 3
b/xf86drmMode.c | 92 +++
b/xf86drmMode.h | 14
debian/patches/02_build_libkms_against_in_tree_drm.diff | 17
44 files changed, 1830 insertions(+), 227 deletions(-)
diff --git a/.gitignore b/.gitignore
index 243457e..28c77c5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,8 @@ libdrm.pc
libdrm_intel.pc
libdrm_nouveau.pc
libdrm_radeon.pc
+libdrm_omap.pc
+libdrm_exynos.pc
libkms.pc
libtool
ltmain.sh
@@ -76,3 +78,5 @@ tests/modeprint/modeprint
tests/modetest/modetest
tests/kmstest/kmstest
tests/vbltest/vbltest
+tests/radeon/radeon_ttm
+man/*.3
diff --git a/ChangeLog b/ChangeLog
index b36beb3..53b397c 100644
diff --git a/Makefile.am b/Makefile.am
index 4f625a1..8ecd9d9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -45,7 +45,11 @@ if HAVE_OMAP
OMAP_SUBDIR = omap
endif
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) tests include
+if HAVE_EXYNOS
+EXYNOS_SUBDIR = exynos
+endif
+
+SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) tests include man
libdrm_la_LTLIBRARIES = libdrm.la
libdrm_ladir = $(libdir)
diff --git a/autogen.sh b/autogen.sh
index 30d679f..3f190ba 100755
--- a/autogen.sh
+++ b/autogen.sh
@@ -3,4 +3,4 @@
test -n "$srcdir" || srcdir=`dirname "$0"`
test -n "$srcdir" || srcdir=.
autoreconf --force --install --verbose "$srcdir"
-test -n "$NOCONFIGURE" || "$srcdir/configure" "$@"
+test -n "$NOCONFIGURE" || "$srcdir/configure" --enable-maintainer-mode "$@"
diff --git a/configure.ac b/configure.ac
index 1ba7eba..0c19929 100644
--- a/configure.ac
+++ b/configure.ac
@@ -20,7 +20,7 @@
AC_PREREQ([2.63])
AC_INIT([libdrm],
- [2.4.33],
+ [2.4.40],
[https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
[libdrm])
@@ -35,6 +35,27 @@ AM_MAINTAINER_MODE([enable])
# Enable quiet compiles on automake 1.11.
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
+if test x$LIB_MAN_SUFFIX = x ; then
+ LIB_MAN_SUFFIX=3
+fi
+if test x$LIB_MAN_DIR = x ; then
+ LIB_MAN_DIR='$(mandir)/man$(LIB_MAN_SUFFIX)'
+fi
+AC_SUBST([LIB_MAN_SUFFIX])
+AC_SUBST([LIB_MAN_DIR])
+
+MAN_SUBSTS="\
+ -e 's|__vendorversion__|\"\$(PACKAGE_STRING)\" |' \
+ -e 's|__projectroot__|\$(prefix)|g' \
+ -e 's|__apploaddir__|\$(appdefaultdir)|g' \
+ -e 's|__appmansuffix__|\$(APP_MAN_SUFFIX)|g' \
+ -e 's|__drivermansuffix__|\$(DRIVER_MAN_SUFFIX)|g' \
+ -e 's|__adminmansuffix__|\$(ADMIN_MAN_SUFFIX)|g' \
+ -e 's|__libmansuffix__|\$(LIB_MAN_SUFFIX)|g' \
+ -e 's|__miscmansuffix__|\$(MISC_MAN_SUFFIX)|g' \
+ -e 's|__filemansuffix__|\$(FILE_MAN_SUFFIX)|g'"
+AC_SUBST([MAN_SUBSTS])
+
# Check for programs
AC_PROG_CC
@@ -73,21 +94,26 @@ AC_ARG_ENABLE(radeon,
[Enable support for radeon's KMS API (default: auto)]),
[RADEON=$enableval], [RADEON=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(nouveau,
+ AS_HELP_STRING([--disable-nouveau],
+ [Enable support for nouveau's KMS API (default: auto)]),
+ [NOUVEAU=$enableval], [NOUVEAU=auto])
-AC_ARG_ENABLE(nouveau-experimental-api,
- AS_HELP_STRING([--enable-nouveau-experimental-api],
- [Enable support for nouveau's experimental API (default: disabled)]),
- [NOUVEAU=$enableval], [NOUVEAU=no])
+AC_ARG_ENABLE(vmwgfx,
+ AS_HELP_STRING([--disable-vmwgfx],
+ [Enable support for vmwgfx's KMS API (default: yes)]),
+ [VMWGFX=$enableval], [VMWGFX=yes])
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], [
@@ -128,7 +154,7 @@ MAYBE_WARN="-Wall -Wextra \
-Wpointer-arith -Wwrite-strings -Wstrict-prototypes \
-Wmissing-prototypes -Wmissing-declarations -Wnested-externs \
-Wpacked -Wswitch-enum -Wmissing-format-attribute \
--Wstrict-aliasing=2 -Winit-self -Wunsafe-loop-optimizations \
+-Wstrict-aliasing=2 -Winit-self \
-Wdeclaration-after-statement -Wold-style-definition \
-Wno-missing-field-initializers -Wno-unused-parameter \
-Wno-attributes -Wno-long-long -Winline"
@@ -191,11 +217,28 @@ 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
+
+AC_ARG_ENABLE([cairo-tests],
+ [AS_HELP_STRING([--enable-cairo-tests],
+ [Enable support for Cairo rendering in tests (default: auto)])],
+ [CAIRO=$enableval], [CAIRO=auto])
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])
+AC_MSG_CHECKING([whether to enable Cairo tests])
+if test "x$CAIRO" = xauto; then
+ CAIRO="$HAVE_CAIRO"
fi
-AM_CONDITIONAL(HAVE_CAIRO, [test "x$HAVE_CAIRO" = xyes])
+if test "x$CAIRO" = xyes; then
+ if ! test "x$HAVE_CAIRO" = xyes; then
+ AC_MSG_ERROR([Cairo support required but not present])
+ fi
+ AC_DEFINE(HAVE_CAIRO, 1, [Have Cairo support])
+fi
+AC_MSG_RESULT([$CAIRO])
+AM_CONDITIONAL(HAVE_CAIRO, [test "x$CAIRO" = xyes])
# For enumerating devices in test case
PKG_CHECK_MODULES(LIBUDEV, libudev, [HAVE_LIBUDEV=yes], [HAVE_LIBUDEV=no])
@@ -204,7 +247,7 @@ if test "x$HAVE_LIBUDEV" = xyes; then
fi
AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes])
-if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
+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,
[
@@ -252,7 +295,14 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
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
@@ -263,6 +313,9 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno"; then
if test "x$RADEON" != "xno"; then
RADEON=yes
fi
+ if test "x$NOUVEAU" != "xno"; then
+ NOUVEAU=yes
+ fi
fi
fi
@@ -279,6 +332,7 @@ 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
@@ -302,6 +356,8 @@ AC_CONFIG_FILES([
nouveau/libdrm_nouveau.pc
omap/Makefile
omap/libdrm_omap.pc
+ exynos/Makefile
+ exynos/libdrm_exynos.pc
tests/Makefile
tests/modeprint/Makefile
tests/modetest/Makefile
@@ -310,6 +366,7 @@ AC_CONFIG_FILES([
tests/vbltest/Makefile
include/Makefile
include/drm/Makefile
+ man/Makefile
libdrm.pc])
AC_OUTPUT
@@ -322,4 +379,5 @@ echo " vmwgfx API $VMWGFX"
echo " Radeon API $RADEON"
echo " Nouveau API $NOUVEAU"
echo " OMAP API $OMAP"
+echo " EXYNOS API $EXYNOS"
echo ""
diff --git a/debian/changelog b/debian/changelog
index 6408491..fe51436 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,32 @@
+libdrm (2.4.40-1~deb7u1) UNRELEASED; urgency=low
+
+ * Revert nouveau to the 2.4.33 state (ie before the rewrite).
+ * Revert addition of libdrm2-udeb.
+ * Bump libdrm2 shlibs to 2.4.38.
+
+ -- Julien Cristau <jcristau@debian.org> Tue, 25 Dec 2012 13:08:50 +0100
+
+libdrm (2.4.40-1) experimental; urgency=low
+
+ [ Maarten Lankhorst ]
+ * New upstream release.
+ - Nouveau ABI change, replace libdrm-nouveau1a with libdrm-nouveau2.
+
+ [ Timo Aaltonen ]
+ * Bump libdrm-intel1's and libdrm-nouveau2's shlibs due to new symbols.
+ * Hardcode the version for libdrm-omap1's shlibs.
+
+ [ Christopher James Halse Rogers ]
+ * Add libdrm2-udeb; Xserver 1.13 wants libdrm for hotplug config, so
+ will be needed for the 1.13 xserver-xorg-core-udeb.
+
+ [ Sven Joachim ]
+ * Bump libdrm-radeon1's symbols and shlibs.
+ * Mark some internal libdrm-nouveau2 symbols as private.
+ * Drop patch 02_build_libkms_against_in_tree_drm.diff, applied upstream.
+
+ -- Julien Cristau <jcristau@debian.org> Sat, 17 Nov 2012 18:50:33 +0100
+
libdrm (2.4.33-3) unstable; urgency=low
* Add missing dependency on libdrm-omap1 to libdrm-dev (thanks, Robert
diff --git a/debian/control b/debian/control
index 5b5d9f6..354f97d 100644
--- a/debian/control
+++ b/debian/control
@@ -3,7 +3,7 @@ Priority: optional
Maintainer: Debian X Strike Force <debian-x@lists.debian.org>
Uploaders: Cyril Brulebois <kibi@debian.org>
Build-Depends:
- debhelper (>= 8.1.2ubuntu2),
+ debhelper (>= 9),
dh-autoreconf,
quilt,
libx11-dev,
diff --git a/debian/libdrm-dev.install b/debian/libdrm-dev.install
index 76f28fa..e1ca993 100644
--- a/debian/libdrm-dev.install
+++ b/debian/libdrm-dev.install
@@ -2,3 +2,4 @@ usr/include/*
usr/lib/*/lib*.a
usr/lib/*/lib*.so
usr/lib/*/pkgconfig/*
+usr/share/man/man3
diff --git a/debian/libdrm-intel1.symbols b/debian/libdrm-intel1.symbols
index a381740..8f5b9fe 100644
--- a/debian/libdrm-intel1.symbols
+++ b/debian/libdrm-intel1.symbols
@@ -11,6 +11,8 @@ libdrm_intel.so.1 libdrm-intel1 #MINVER#
drm_intel_bo_fake_disable_backing_store@Base 2.4.1
drm_intel_bo_flink@Base 2.4.1
drm_intel_bo_gem_create_from_name@Base 2.4.1
+ drm_intel_bo_gem_create_from_prime@Base 2.4.38
+ drm_intel_bo_gem_export_to_prime@Base 2.4.38
drm_intel_bo_get_subdata@Base 2.4.1
drm_intel_bo_get_tiling@Base 2.4.1
drm_intel_bo_is_reusable@Base 2.4.21
@@ -39,6 +41,7 @@ libdrm_intel.so.1 libdrm-intel1 #MINVER#
drm_intel_bufmgr_gem_get_devid@Base 2.4.32
drm_intel_bufmgr_gem_init@Base 2.4.1
drm_intel_bufmgr_gem_set_aub_dump@Base 2.4.32
+ drm_intel_bufmgr_gem_set_aub_annotations@Base 2.4.34
drm_intel_bufmgr_gem_set_vma_cache_size@Base 2.4.29
drm_intel_bufmgr_set_debug@Base 2.4.1
drm_intel_decode@Base 2.4.30
@@ -50,13 +53,18 @@ libdrm_intel.so.1 libdrm-intel1 #MINVER#
drm_intel_decode_set_output_file@Base 2.4.30
drm_intel_gem_bo_aub_dump_bmp@Base 2.4.32
drm_intel_gem_bo_clear_relocs@Base 2.4.27
+ drm_intel_gem_bo_context_exec@Base 2.4.36
drm_intel_gem_bo_get_reloc_count@Base 2.4.27
drm_intel_gem_bo_map_gtt@Base 2.4.3
drm_intel_gem_bo_map_unsynchronized@Base 2.4.32
drm_intel_gem_bo_start_gtt_access@Base 2.4.3
drm_intel_gem_bo_unmap_gtt@Base 2.4.9
+ drm_intel_gem_bo_wait@Base 2.4.36
+ drm_intel_gem_context_create@Base 2.4.37
+ drm_intel_gem_context_destroy@Base 2.4.37
drm_intel_get_aperture_sizes@Base 2.4.26
drm_intel_get_pipe_from_crtc_id@Base 2.4.11
+ drm_intel_reg_read@Base 2.4.38
drm_mmAllocMem@Base 2.4.1
drm_mmDestroy@Base 2.4.1
drm_mmDumpMemInfo@Base 2.4.1
diff --git a/debian/libdrm-omap1.symbols b/debian/libdrm-omap1.symbols
index 5ad0f17..0c12475 100644
--- a/debian/libdrm-omap1.symbols
+++ b/debian/libdrm-omap1.symbols
@@ -2,14 +2,18 @@ libdrm_omap.so.1 libdrm-omap1 #MINVER#
omap_bo_cpu_fini@Base 2.4.33
omap_bo_cpu_prep@Base 2.4.33
omap_bo_del@Base 2.4.33
+ omap_bo_dmabuf@Base 2.4.34
+ omap_bo_from_dmabuf@Base 2.4.38
omap_bo_from_name@Base 2.4.33
omap_bo_get_name@Base 2.4.33
omap_bo_handle@Base 2.4.33
omap_bo_map@Base 2.4.33
omap_bo_new@Base 2.4.33
omap_bo_new_tiled@Base 2.4.33
+ omap_bo_ref@Base 2.4.38
omap_bo_size@Base 2.4.33
omap_device_del@Base 2.4.33
omap_device_new@Base 2.4.33
+ omap_device_ref@Base 2.4.38
omap_get_param@Base 2.4.33
omap_set_param@Base 2.4.33
diff --git a/debian/libdrm-radeon1.symbols b/debian/libdrm-radeon1.symbols
index 557be89..e9578a6 100644
--- a/debian/libdrm-radeon1.symbols
+++ b/debian/libdrm-radeon1.symbols
@@ -52,9 +52,11 @@ libdrm_radeon.so.1 libdrm-radeon1 #MINVER#
radeon_cs_space_reset_bos@Base 2.4.17
radeon_cs_space_set_flush@Base 2.4.17
radeon_cs_write_reloc@Base 2.4.17
+ radeon_gem_bo_open_prime@Base 2.4.39
radeon_gem_get_kernel_name@Base 2.4.17
radeon_gem_get_reloc_in_cs@Base 2.4.20
radeon_gem_name_bo@Base 2.4.17
+ radeon_gem_prime_share_bo@Base 2.4.39
radeon_gem_set_domain@Base 2.4.17
radeon_surface_best@Base 2.4.31
radeon_surface_init@Base 2.4.31
diff --git a/debian/libdrm2.symbols b/debian/libdrm2.symbols
index 0f70434..c4047c4 100644
--- a/debian/libdrm2.symbols
+++ b/debian/libdrm2.symbols
@@ -89,6 +89,7 @@ libdrm.so.2 libdrm2 #MINVER#
drmModeFreeEncoder@Base 2.4.3
drmModeFreeFB@Base 2.4.3
drmModeFreeModeInfo@Base 2.4.3
+ drmModeFreeObjectProperties@Base 2.4.36
drmModeFreePlane@Base 2.4.30
drmModeFreePlaneResources@Base 2.4.31
drmModeFreeProperty@Base 2.4.3
@@ -104,6 +105,8 @@ libdrm.so.2 libdrm2 #MINVER#
drmModeGetPropertyBlob@Base 2.4.3
drmModeGetResources@Base 2.4.3
drmModeMoveCursor@Base 2.4.3
+ drmModeObjectGetProperties@Base 2.4.36
+ drmModeObjectSetProperty@Base 2.4.36
drmModePageFlip@Base 2.4.17
drmModeRmFB@Base 2.4.3
drmModeSetCrtc@Base 2.4.3
@@ -113,6 +116,8 @@ libdrm.so.2 libdrm2 #MINVER#
drmOpen@Base 2.3.1
drmOpenControl@Base 2.4.3
drmOpenOnce@Base 2.3.1
+ drmPrimeFDToHandle@Base 2.4.38
+ drmPrimeHandleToFD@Base 2.4.38
drmRandom@Base 2.3.1
drmRandomCreate@Base 2.3.1
drmRandomDestroy@Base 2.3.1
diff --git a/debian/patches/02_build_libkms_against_in_tree_drm.diff b/debian/patches/02_build_libkms_against_in_tree_drm.diff
deleted file mode 100644
index 25f8e43..0000000
--- a/debian/patches/02_build_libkms_against_in_tree_drm.diff
+++ /dev/null
@@ -1,17 +0,0 @@
-Description: Add libdrm to LIBADD as libkms uses symbols from libdrm
-Author: Christopher Halse Rogers <christopher.halse.rogers@canonical.com>
-Bug: https://bugs.freedesktop.org/show_bug.cgi?id=26852
-
-Index: libdrm/libkms/Makefile.am
-===================================================================
---- libdrm.orig/libkms/Makefile.am
-+++ libdrm/libkms/Makefile.am
-@@ -6,7 +6,7 @@ AM_CFLAGS = \
- libkms_la_LTLIBRARIES = libkms.la
- libkms_ladir = $(libdir)
- libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined
--libkms_la_LIBADD =
-+libkms_la_LIBADD = ../libdrm.la
-
- #if HAVE_LIBUDEV
- #libkms_la_LIBADD += $(LIBUDEV_LIBS)
diff --git a/debian/patches/revert-nouveau-rewrite.diff b/debian/patches/revert-nouveau-rewrite.diff
new file mode 100644
index 0000000..76bec4b
diff --git a/debian/patches/series b/debian/patches/series
index b1a73f8..c20e4b9 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,3 +1,3 @@
01_default_perms.diff
-02_build_libkms_against_in_tree_drm.diff
03_build_against_librt.diff
+revert-nouveau-rewrite.diff
diff --git a/debian/rules b/debian/rules
index 44926b1..bb23d84 100755
--- a/debian/rules
+++ b/debian/rules
@@ -13,8 +13,8 @@ ifeq (linux, $(DEB_HOST_ARCH_OS))
confflags += --enable-udev
confflags += --enable-libkms
LIBKMS = yes
- confflags += --enable-vmwgfx-experimental-api
- confflags += --enable-nouveau-experimental-api
+ confflags += --enable-vmwgfx
+ confflags += --enable-nouveau
NOUVEAU = yes
confflags += --enable-radeon
RADEON = yes
@@ -22,8 +22,8 @@ else
confflags += --disable-udev
confflags += --disable-libkms
LIBKMS = no
- confflags += --disable-vmwgfx-experimental-api
- confflags += --disable-nouveau-experimental-api
+ confflags += --disable-vmwgfx
+ confflags += --disable-nouveau
NOUVEAU = no
confflags += --disable-radeon
RADEON = no
@@ -88,18 +88,18 @@ endif
dh_strip -s --remaining-packages
override_dh_makeshlibs:
- dh_makeshlibs -plibdrm2 -V'libdrm2 (>= 2.4.31)' -- -c4
+ dh_makeshlibs -plibdrm2 -V'libdrm2 (>= 2.4.38)' -- -c4
ifeq ($(INTEL), yes)
- dh_makeshlibs -plibdrm-intel1 -V'libdrm-intel1 (>= 2.4.32)' -- -c4
+ dh_makeshlibs -plibdrm-intel1 -V'libdrm-intel1 (>= 2.4.38)' -- -c4
endif
ifeq ($(NOUVEAU), yes)
dh_makeshlibs -plibdrm-nouveau1a -V'libdrm-nouveau1a (>= 2.4.23)' -- -c4
endif
ifeq ($(RADEON), yes)
- dh_makeshlibs -plibdrm-radeon1 -V'libdrm-radeon1 (>= 2.4.31)' -- -c4
+ dh_makeshlibs -plibdrm-radeon1 -V'libdrm-radeon1 (>= 2.4.39)' -- -c4
endif
ifeq ($(OMAP), yes)
- dh_makeshlibs -plibdrm-omap1 -V'libdrm-omap1' -- -c4
+ dh_makeshlibs -plibdrm-omap1 -V'libdrm-omap1 (>= 2.4.38)' -- -c4
endif
ifeq ($(LIBKMS), yes)
dh_makeshlibs -plibkms1 -V'libkms1' -- -c4
diff --git a/exynos/Makefile.am b/exynos/Makefile.am
new file mode 100644
index 0000000..e782d34
diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
new file mode 100644
index 0000000..4db755e
diff --git a/exynos/exynos_drm.h b/exynos/exynos_drm.h
new file mode 100644
index 0000000..aa97b22
diff --git a/exynos/exynos_drmif.h b/exynos/exynos_drmif.h
new file mode 100644
index 0000000..92f613e
diff --git a/exynos/libdrm_exynos.pc.in b/exynos/libdrm_exynos.pc.in
new file mode 100644
index 0000000..5ce9118
diff --git a/include/drm/drm.h b/include/drm/drm.h
index 8adb9d5..a847689 100644
--- a/include/drm/drm.h
+++ b/include/drm/drm.h
@@ -618,6 +618,17 @@ struct drm_get_cap {
__u64 value;
};
+#define DRM_CLOEXEC O_CLOEXEC
+struct drm_prime_handle {
+ __u32 handle;
+
+ /** Flags.. only applicable for handle->fd */
+ __u32 flags;
+
+ /** Returned dmabuf file descriptor */
+ __s32 fd;
+};
+
#include "drm_mode.h"
#define DRM_IOCTL_BASE 'd'
@@ -674,6 +685,9 @@ struct drm_get_cap {
#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
+#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)
+#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)
+
#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode)
@@ -717,6 +731,8 @@ struct drm_get_cap {
#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane)
#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane)
#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
+#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
+#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
/**
* Device specific ioctls should only be in their respective headers
@@ -760,6 +776,12 @@ struct drm_event_vblank {
#define DRM_CAP_DUMB_BUFFER 0x1
#define DRM_CAP_VBLANK_HIGH_CRTC 0x2
+#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
+#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
+#define DRM_CAP_PRIME 0x5
+
+#define DRM_PRIME_CAP_IMPORT 0x1
+#define DRM_PRIME_CAP_EXPORT 0x2
/* typedef area */
typedef struct drm_clip_rect drm_clip_rect_t;
diff --git a/include/drm/drm_mode.h b/include/drm/drm_mode.h
index f36c61a..62ba997 100644
--- a/include/drm/drm_mode.h
+++ b/include/drm/drm_mode.h
@@ -226,6 +226,7 @@ struct drm_mode_get_connector {
#define DRM_MODE_PROP_IMMUTABLE (1<<2)
#define DRM_MODE_PROP_ENUM (1<<3) /* enumerated type with text strings */
#define DRM_MODE_PROP_BLOB (1<<4)
+#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */
struct drm_mode_property_enum {
__u64 value;
@@ -250,6 +251,30 @@ struct drm_mode_connector_set_property {
__u32 connector_id;
};
+#define DRM_MODE_OBJECT_CRTC 0xcccccccc
+#define DRM_MODE_OBJECT_CONNECTOR 0xc0c0c0c0
+#define DRM_MODE_OBJECT_ENCODER 0xe0e0e0e0
+#define DRM_MODE_OBJECT_MODE 0xdededede
+#define DRM_MODE_OBJECT_PROPERTY 0xb0b0b0b0
+#define DRM_MODE_OBJECT_FB 0xfbfbfbfb
+#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
+#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
+
+struct drm_mode_obj_get_properties {
+ __u64 props_ptr;
+ __u64 prop_values_ptr;
+ __u32 count_props;
+ __u32 obj_id;
+ __u32 obj_type;
+};
+
+struct drm_mode_obj_set_property {
+ __u64 value;
+ __u32 prop_id;
+ __u32 obj_id;
+ __u32 obj_type;
+};
+
struct drm_mode_get_blob {
__u32 blob_id;
__u32 length;
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index af3ce17..7e9e9bd 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -33,6 +33,7 @@
* subject to backwards-compatibility constraints.
*/
+
/* Each region is a minimum of 16k, and there are at most 255 of them.
*/
#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use
@@ -191,6 +192,12 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_EXECBUFFER2 0x29
#define DRM_I915_GET_SPRITE_COLORKEY 0x2a
#define DRM_I915_SET_SPRITE_COLORKEY 0x2b
+#define DRM_I915_GEM_WAIT 0x2c
+#define DRM_I915_GEM_CONTEXT_CREATE 0x2d
+#define DRM_I915_GEM_CONTEXT_DESTROY 0x2e
+#define DRM_I915_GEM_SET_CACHEING 0x2f
+#define DRM_I915_GEM_GET_CACHEING 0x30
+#define DRM_I915_REG_READ 0x31
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
@@ -215,6 +222,8 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_PIN, struct drm_i915_gem_pin)
#define DRM_IOCTL_I915_GEM_UNPIN DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_UNPIN, struct drm_i915_gem_unpin)
#define DRM_IOCTL_I915_GEM_BUSY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_BUSY, struct drm_i915_gem_busy)
+#define DRM_IOCTL_I915_GEM_SET_CACHEING DRM_IOW(DRM_COMMAND_BASE + DRM_I915_GEM_SET_CACHEING, struct drm_i915_gem_cacheing)
+#define DRM_IOCTL_I915_GEM_GET_CACHEING DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_GET_CACHEING, struct drm_i915_gem_cacheing)
#define DRM_IOCTL_I915_GEM_THROTTLE DRM_IO ( DRM_COMMAND_BASE + DRM_I915_GEM_THROTTLE)
#define DRM_IOCTL_I915_GEM_ENTERVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_ENTERVT)
#define DRM_IOCTL_I915_GEM_LEAVEVT DRM_IO(DRM_COMMAND_BASE + DRM_I915_GEM_LEAVEVT)
@@ -234,6 +243,10 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_OVERLAY_ATTRS DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_OVERLAY_ATTRS, struct drm_intel_overlay_attrs)
#define DRM_IOCTL_I915_SET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
#define DRM_IOCTL_I915_GET_SPRITE_COLORKEY DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_SET_SPRITE_COLORKEY, struct drm_intel_sprite_colorkey)
+#define DRM_IOCTL_I915_GEM_WAIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_WAIT, struct drm_i915_gem_wait)
+#define DRM_IOCTL_I915_GEM_CONTEXT_CREATE DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_CREATE, struct drm_i915_gem_context_create)
+#define DRM_IOCTL_I915_GEM_CONTEXT_DESTROY DRM_IOW (DRM_COMMAND_BASE + DRM_I915_GEM_CONTEXT_DESTROY, struct drm_i915_gem_context_destroy)
+#define DRM_IOCTL_I915_REG_READ DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_REG_READ, struct drm_i915_reg_read)
/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
@@ -287,7 +300,9 @@ typedef struct drm_i915_irq_wait {
#define I915_PARAM_HAS_EXEC_CONSTANTS 14
#define I915_PARAM_HAS_RELAXED_DELTA 15
#define I915_PARAM_HAS_GEN7_SOL_RESET 16
-#define I915_PARAM_HAS_LLC 17
+#define I915_PARAM_HAS_LLC 17
+#define I915_PARAM_HAS_ALIASING_PPGTT 18
+#define I915_PARAM_HAS_WAIT_TIMEOUT 19
typedef struct drm_i915_getparam {
int param;
@@ -646,13 +661,19 @@ struct drm_i915_gem_execbuffer2 {
#define I915_EXEC_CONSTANTS_ABSOLUTE (1<<6)
#define I915_EXEC_CONSTANTS_REL_SURFACE (2<<6) /* gen4/5 only */
__u64 flags;
- __u64 rsvd1;
+ __u64 rsvd1; /* now used for context info */
__u64 rsvd2;
};
/** Resets the SO write offset registers for transform feedback on gen7. */
#define I915_EXEC_GEN7_SOL_RESET (1<<8)
+#define I915_EXEC_CONTEXT_ID_MASK (0xffffffff)
+#define i915_execbuffer2_set_context_id(eb2, context) \
+ (eb2).rsvd1 = context & I915_EXEC_CONTEXT_ID_MASK
+#define i915_execbuffer2_get_context_id(eb2) \
+ ((eb2).rsvd1 & I915_EXEC_CONTEXT_ID_MASK)
+
struct drm_i915_gem_pin {
/** Handle of the buffer to be pinned. */
__u32 handle;
@@ -675,10 +696,31 @@ struct drm_i915_gem_busy {
/** Handle of the buffer to check for busy */
__u32 handle;
- /** Return busy status (1 if busy, 0 if idle) */
+ /** Return busy status (1 if busy, 0 if idle).
+ * The high word is used to indicate on which rings the object
+ * currently resides:
+ * 16:31 - busy (r or r/w) rings (16 render, 17 bsd, 18 blt, etc)
+ */
__u32 busy;
};
+#define I915_CACHEING_NONE 0
+#define I915_CACHEING_CACHED 1
+
+struct drm_i915_gem_cacheing {
+ /**
+ * Handle of the buffer to set/get the cacheing level of. */
+ __u32 handle;
+
+ /**
+ * Cacheing level to apply or return value
+ *
+ * bits0-15 are for generic cacheing control (i.e. the above defined
+ * values). bits16-31 are reserved for platform-specific variations
+ * (e.g. l3$ caching on gen7). */
+ __u32 cacheing;
+};
+
#define I915_TILING_NONE 0
#define I915_TILING_X 1
#define I915_TILING_Y 2
@@ -876,4 +918,27 @@ struct drm_intel_sprite_colorkey {
__u32 flags;
};
+struct drm_i915_gem_wait {
+ /** Handle of BO we shall wait on */
+ __u32 bo_handle;
+ __u32 flags;
+ /** Number of nanoseconds to wait, Returns time remaining. */
+ __s64 timeout_ns;
+};
+
+struct drm_i915_gem_context_create {
+ /* output: id of new context*/
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+struct drm_i915_gem_context_destroy {
+ __u32 ctx_id;
+ __u32 pad;
+};
+
+struct drm_i915_reg_read {
+ __u64 offset;
+ __u64 val; /* Return value */
+};
#endif /* _I915_DRM_H_ */
diff --git a/intel/Makefile.am b/intel/Makefile.am
index dc01a96..f49b099 100644
--- a/intel/Makefile.am
+++ b/intel/Makefile.am
@@ -77,6 +77,6 @@ EXTRA_DIST = \
$(BATCHES:.batch=.batch-ref.txt) \
tests/test-batch.sh
-test_decode_LDADD = libdrm_intel.la
+test_decode_LDADD = libdrm_intel.la ../libdrm.la
pkgconfig_DATA = libdrm_intel.pc
diff --git a/intel/intel_bufmgr.h b/intel/intel_bufmgr.h
index 45389e1..8d7f239 100644
--- a/intel/intel_bufmgr.h
+++ b/intel/intel_bufmgr.h
@@ -41,6 +41,7 @@
struct drm_clip_rect;
typedef struct _drm_intel_bufmgr drm_intel_bufmgr;
+typedef struct _drm_intel_context drm_intel_context;
typedef struct _drm_intel_bo drm_intel_bo;
struct _drm_intel_bo {
@@ -92,6 +93,12 @@ enum aub_dump_bmp_format {
AUB_DUMP_BMP_FORMAT_ARGB_8888 = 7,
};
+typedef struct _drm_intel_aub_annotation {
+ uint32_t type;
+ uint32_t subtype;
+ uint32_t ending_offset;
+} drm_intel_aub_annotation;
+
#define BO_ALLOC_FOR_RENDER (1<<0)
drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
@@ -169,11 +176,25 @@ void drm_intel_gem_bo_aub_dump_bmp(drm_intel_bo *bo,
int x1, int y1, int width, int height,
enum aub_dump_bmp_format format,
int pitch, int offset);
+void
+drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
+ drm_intel_aub_annotation *annotations,
+ unsigned count);
int drm_intel_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id);
int drm_intel_get_aperture_sizes(int fd, size_t *mappable, size_t *total);
int drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr);
+int drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns);
+
+drm_intel_context *drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr);
+void drm_intel_gem_context_destroy(drm_intel_context *ctx);
+int drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
+ int used, unsigned int flags);
+
+int drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd);
+drm_intel_bo *drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr,
+ int prime_fd, int size);
/* drm_intel_bufmgr_fake.c */
drm_intel_bufmgr *drm_intel_bufmgr_fake_init(int fd,
@@ -220,6 +241,9 @@ void drm_intel_decode_set_head_tail(struct drm_intel_decode *ctx,
void drm_intel_decode_set_output_file(struct drm_intel_decode *ctx, FILE *out);
void drm_intel_decode(struct drm_intel_decode *ctx);
+int drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
+ uint32_t offset,
+ uint64_t *result);
/** @{ Compatibility defines to keep old code building despite the symbol rename
* from dri_* to drm_intel_*
diff --git a/intel/intel_bufmgr_gem.c b/intel/intel_bufmgr_gem.c
index 3c91090..8d45839 100644
--- a/intel/intel_bufmgr_gem.c
+++ b/intel/intel_bufmgr_gem.c
@@ -119,6 +119,7 @@ typedef struct _drm_intel_bufmgr_gem {
unsigned int has_blt : 1;
unsigned int has_relaxed_fencing : 1;
unsigned int has_llc : 1;
+ unsigned int has_wait_timeout : 1;
unsigned int bo_reuse : 1;
unsigned int no_exec : 1;
bool fenced_relocs;
@@ -221,6 +222,9 @@ struct _drm_intel_bo_gem {
bool mapped_cpu_write;
uint32_t aub_offset;
+
+ drm_intel_aub_annotation *aub_annotations;
+ unsigned aub_annotation_count;
};
static unsigned int
@@ -735,6 +739,8 @@ retry:
bo_gem->used_as_reloc_target = false;
bo_gem->has_error = false;
bo_gem->reusable = true;
+ bo_gem->aub_annotations = NULL;
+ bo_gem->aub_annotation_count = 0;
drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
@@ -926,6 +932,7 @@ drm_intel_gem_bo_free(drm_intel_bo *bo)
DBG("DRM_IOCTL_GEM_CLOSE %d failed (%s): %s\n",
bo_gem->gem_handle, bo_gem->name, strerror(errno));
}
+ free(bo_gem->aub_annotations);
free(bo);
}
@@ -1473,6 +1480,58 @@ drm_intel_gem_bo_wait_rendering(drm_intel_bo *bo)
}
/**
+ * Waits on a BO for the given amount of time.
+ *
+ * @bo: buffer object to wait for
+ * @timeout_ns: amount of time to wait in nanoseconds.
+ * If value is less than 0, an infinite wait will occur.
+ *
+ * Returns 0 if the wait was successful ie. the last batch referencing the
+ * object has completed within the allotted time. Otherwise some negative return
+ * value describes the error. Of particular interest is -ETIME when the wait has
+ * failed to yield the desired result.
+ *
+ * Similar to drm_intel_gem_bo_wait_rendering except a timeout parameter allows
+ * the operation to give up after a certain amount of time. Another subtle
+ * difference is the internal locking semantics are different (this variant does
+ * not hold the lock for the duration of the wait). This makes the wait subject
+ * to a larger userspace race window.
+ *
+ * The implementation shall wait until the object is no longer actively
+ * referenced within a batch buffer at the time of the call. The wait will
+ * not guarantee that the buffer is re-issued via another thread, or an flinked
+ * handle. Userspace must make sure this race does not occur if such precision
+ * is important.
+ */
+int drm_intel_gem_bo_wait(drm_intel_bo *bo, int64_t timeout_ns)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+ struct drm_i915_gem_wait wait;
+ int ret;
+
+ if (!bufmgr_gem->has_wait_timeout) {
+ DBG("%s:%d: Timed wait is not supported. Falling back to "
+ "infinite wait\n", __FILE__, __LINE__);
+ if (timeout_ns) {
+ drm_intel_gem_bo_wait_rendering(bo);
+ return 0;
+ } else {
+ return drm_intel_gem_bo_busy(bo) ? -ETIME : 0;
+ }
+ }
+
+ wait.bo_handle = bo_gem->gem_handle;
+ wait.timeout_ns = timeout_ns;
+ wait.flags = 0;
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_WAIT, &wait);
+ if (ret == -1)
+ return -errno;
+
+ return ret;
+}
+
+/**
* Sets the object to the GTT read and possibly write domain, used by the X
* 2D driver in the absence of kernel support to do drm_intel_gem_bo_map_gtt().
*
@@ -1880,26 +1939,58 @@ aub_write_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype,
aub_write_bo_data(bo, offset, size);
}
+/**
+ * Break up large objects into multiple writes. Otherwise a 128kb VBO
+ * would overflow the 16 bits of size field in the packet header and
+ * everything goes badly after that.
+ */
static void
-aub_write_bo(drm_intel_bo *bo)
+aub_write_large_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype,
+ uint32_t offset, uint32_t size)
{
uint32_t block_size;
- uint32_t offset;
+ uint32_t sub_offset;
- aub_bo_get_address(bo);
-
- /* Break up large objects into multiple writes. Otherwise a
- * 128kb VBO would overflow the 16 bits of size field in the
- * packet header and everything goes badly after that.
- */
- for (offset = 0; offset < bo->size; offset += block_size) {
- block_size = bo->size - offset;
+ for (sub_offset = 0; sub_offset < size; sub_offset += block_size) {
+ block_size = size - sub_offset;
if (block_size > 8 * 4096)
block_size = 8 * 4096;
- aub_write_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
- offset, block_size);
+ aub_write_trace_block(bo, type, subtype, offset + sub_offset,
+ block_size);
+ }
+}
+
+static void
+aub_write_bo(drm_intel_bo *bo)
+{
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+ uint32_t offset = 0;
+ unsigned i;
+
+ aub_bo_get_address(bo);
+
+ /* Write out each annotated section separately. */
+ for (i = 0; i < bo_gem->aub_annotation_count; ++i) {
+ drm_intel_aub_annotation *annotation =
+ &bo_gem->aub_annotations[i];
+ uint32_t ending_offset = annotation->ending_offset;
+ if (ending_offset > bo->size)
+ ending_offset = bo->size;
+ if (ending_offset > offset) {
+ aub_write_large_trace_block(bo, annotation->type,
+ annotation->subtype,
+ offset,
+ ending_offset - offset);
+ offset = ending_offset;
+ }
+ }
+
+ /* Write out any remaining unannotated data */
+ if (offset < bo->size) {
+ aub_write_large_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
+ offset, bo->size - offset);
}
}
@@ -1989,23 +2080,31 @@ aub_exec(drm_intel_bo *bo, int ring_flag, int used)
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
int i;
+ bool batch_buffer_needs_annotations;
if (!bufmgr_gem->aub_file)
return;
- /* Write out all but the batchbuffer to AUB memory */
- for (i = 0; i < bufmgr_gem->exec_count - 1; i++) {
- if (bufmgr_gem->exec_bos[i] != bo)
- aub_write_bo(bufmgr_gem->exec_bos[i]);
+ /* If batch buffer is not annotated, annotate it the best we
+ * can.
+ */
+ batch_buffer_needs_annotations = bo_gem->aub_annotation_count == 0;
+ if (batch_buffer_needs_annotations) {
+ drm_intel_aub_annotation annotations[2] = {
+ { AUB_TRACE_TYPE_BATCH, 0, used },
+ { AUB_TRACE_TYPE_NOTYPE, 0, bo->size }
+ };
+ drm_intel_bufmgr_gem_set_aub_annotations(bo, annotations, 2);
}
- aub_bo_get_address(bo);
+ /* Write out all buffers to AUB memory */
+ for (i = 0; i < bufmgr_gem->exec_count; i++) {
+ aub_write_bo(bufmgr_gem->exec_bos[i]);
+ }
- /* Dump the batchbuffer. */
- aub_write_trace_block(bo, AUB_TRACE_TYPE_BATCH, 0,
- 0, used);
- aub_write_trace_block(bo, AUB_TRACE_TYPE_NOTYPE, 0,
- used, bo->size - used);
+ /* Remove any annotations we added */
+ if (batch_buffer_needs_annotations)
+ drm_intel_bufmgr_gem_set_aub_annotations(bo, NULL, 0);
/* Dump ring buffer */
aub_build_dump_ringbuffer(bufmgr_gem, bo_gem->aub_offset, ring_flag);
@@ -2088,9 +2187,9 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
}
static int
-drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
- drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
- unsigned int flags)
+do_exec2(drm_intel_bo *bo, int used, drm_intel_context *ctx,
+ drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
+ unsigned int flags)
{
drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
struct drm_i915_gem_execbuffer2 execbuf;
@@ -2132,7 +2231,10 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
execbuf.DR1 = 0;
execbuf.DR4 = DR4;
execbuf.flags = flags;
- execbuf.rsvd1 = 0;
+ if (ctx == NULL)
+ i915_execbuffer2_set_context_id(execbuf, 0);
+ else
+ i915_execbuffer2_set_context_id(execbuf, ctx->ctx_id);
execbuf.rsvd2 = 0;
aub_exec(bo, flags, used);
@@ -2180,9 +2282,24 @@ drm_intel_gem_bo_exec2(drm_intel_bo *bo, int used,
drm_clip_rect_t *cliprects, int num_cliprects,
int DR4)
{
- return drm_intel_gem_bo_mrb_exec2(bo, used,
- cliprects, num_cliprects, DR4,
- I915_EXEC_RENDER);
+ return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
+ I915_EXEC_RENDER);
+}
+
+static int
+drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
+ drm_clip_rect_t *cliprects, int num_cliprects, int DR4,
+ unsigned int flags)
+{
+ return do_exec2(bo, used, NULL, cliprects, num_cliprects, DR4,
+ flags);
+}
+
+int
+drm_intel_gem_bo_context_exec(drm_intel_bo *bo, drm_intel_context *ctx,
+ int used, unsigned int flags)
+{
+ return do_exec2(bo, used, ctx, NULL, 0, 0, flags);
}
static int
@@ -2296,6 +2413,75 @@ drm_intel_gem_bo_get_tiling(drm_intel_bo *bo, uint32_t * tiling_mode,
return 0;
}
+drm_intel_bo *
+drm_intel_bo_gem_create_from_prime(drm_intel_bufmgr *bufmgr, int prime_fd, int size)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bufmgr;
+ int ret;
+ uint32_t handle;
+ drm_intel_bo_gem *bo_gem;
+ struct drm_i915_gem_get_tiling get_tiling;
+
+ ret = drmPrimeFDToHandle(bufmgr_gem->fd, prime_fd, &handle);
+ if (ret) {
+ fprintf(stderr,"ret is %d %d\n", ret, errno);
+ return NULL;
+ }
+
+ bo_gem = calloc(1, sizeof(*bo_gem));
+ if (!bo_gem)
+ return NULL;
+
+ bo_gem->bo.size = size;
+ bo_gem->bo.handle = handle;
+ bo_gem->bo.bufmgr = bufmgr;
+
+ bo_gem->gem_handle = handle;
+
+ atomic_set(&bo_gem->refcount, 1);
+
+ bo_gem->name = "prime";
+ bo_gem->validate_index = -1;
+ bo_gem->reloc_tree_fences = 0;
+ bo_gem->used_as_reloc_target = false;
+ bo_gem->has_error = false;
+ bo_gem->reusable = false;
+
+ DRMINITLISTHEAD(&bo_gem->name_list);
+ DRMINITLISTHEAD(&bo_gem->vma_list);
+
+ VG_CLEAR(get_tiling);
+ get_tiling.handle = bo_gem->gem_handle;
+ ret = drmIoctl(bufmgr_gem->fd,
+ DRM_IOCTL_I915_GEM_GET_TILING,
+ &get_tiling);
+ if (ret != 0) {
+ drm_intel_gem_bo_unreference(&bo_gem->bo);
+ return NULL;
+ }
+ bo_gem->tiling_mode = get_tiling.tiling_mode;
+ bo_gem->swizzle_mode = get_tiling.swizzle_mode;
+ /* XXX stride is unknown */
+ drm_intel_bo_gem_set_in_aperture_size(bufmgr_gem, bo_gem);
+
+ return &bo_gem->bo;
+}
+
+int
+drm_intel_bo_gem_export_to_prime(drm_intel_bo *bo, int *prime_fd)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+ if (drmPrimeHandleToFD(bufmgr_gem->fd, bo_gem->gem_handle,
+ DRM_CLOEXEC, prime_fd) != 0)
+ return -errno;
+
+ bo_gem->reusable = false;
+
+ return 0;
+}
+
static int
drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
{
@@ -2723,6 +2909,112 @@ drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
}
}
+drm_intel_context *
+drm_intel_gem_context_create(drm_intel_bufmgr *bufmgr)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
+ struct drm_i915_gem_context_create create;
+ drm_intel_context *context = NULL;
+ int ret;
+
+ VG_CLEAR(create);
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_CREATE, &create);
+ if (ret != 0) {
+ DBG("DRM_IOCTL_I915_GEM_CONTEXT_CREATE failed: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ context = calloc(1, sizeof(*context));
+ context->ctx_id = create.ctx_id;
+ context->bufmgr = bufmgr;
+
+ return context;
+}
+
+void
+drm_intel_gem_context_destroy(drm_intel_context *ctx)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem;
+ struct drm_i915_gem_context_destroy destroy;
+ int ret;
+
+ if (ctx == NULL)
+ return;
+
+ VG_CLEAR(destroy);
+
+ bufmgr_gem = (drm_intel_bufmgr_gem *)ctx->bufmgr;
+ destroy.ctx_id = ctx->ctx_id;
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CONTEXT_DESTROY,
+ &destroy);
+ if (ret != 0)
+ fprintf(stderr, "DRM_IOCTL_I915_GEM_CONTEXT_DESTROY failed: %s\n",
+ strerror(errno));
+
+ free(ctx);
+}
+
+int
+drm_intel_reg_read(drm_intel_bufmgr *bufmgr,
+ uint32_t offset,
+ uint64_t *result)
+{
+ drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
+ struct drm_i915_reg_read reg_read;
+ int ret;
+
+ VG_CLEAR(reg_read);
+ reg_read.offset = offset;
+
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_REG_READ, ®_read);
+
+ *result = reg_read.val;
+ return ret;
+}
+
+
+/**
+ * Annotate the given bo for use in aub dumping.
+ *
+ * \param annotations is an array of drm_intel_aub_annotation objects
+ * describing the type of data in various sections of the bo. Each
+ * element of the array specifies the type and subtype of a section of
+ * the bo, and the past-the-end offset of that section. The elements
+ * of \c annotations must be sorted so that ending_offset is
+ * increasing.
+ *
+ * \param count is the number of elements in the \c annotations array.
+ * If \c count is zero, then \c annotations will not be dereferenced.
+ *
+ * Annotations are copied into a private data structure, so caller may
+ * re-use the memory pointed to by \c annotations after the call
+ * returns.
+ *
+ * Annotations are stored for the lifetime of the bo; to reset to the
+ * default state (no annotations), call this function with a \c count
+ * of zero.
+ */
+void
+drm_intel_bufmgr_gem_set_aub_annotations(drm_intel_bo *bo,
+ drm_intel_aub_annotation *annotations,
+ unsigned count)
+{
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+ unsigned size = sizeof(*annotations) * count;
+ drm_intel_aub_annotation *new_annotations =
+ count > 0 ? realloc(bo_gem->aub_annotations, size) : NULL;
+ if (new_annotations == NULL) {
+ free(bo_gem->aub_annotations);
+ bo_gem->aub_annotations = NULL;
+ bo_gem->aub_annotation_count = 0;
+ return;
+ }
+ memcpy(new_annotations, annotations, size);
+ bo_gem->aub_annotations = new_annotations;
+ bo_gem->aub_annotation_count = count;
+}
+
/**
* Initializes the GEM buffer manager, which uses the kernel to allocate, map,
* and manage map buffer objections.
@@ -2778,9 +3070,11 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
else if (IS_GEN6(bufmgr_gem->pci_device))
bufmgr_gem->gen = 6;
else if (IS_GEN7(bufmgr_gem->pci_device))
- bufmgr_gem->gen = 7;
- else
- assert(0);
+ bufmgr_gem->gen = 7;
+ else {
+ free(bufmgr_gem);
+ return NULL;
+ }
if (IS_GEN3(bufmgr_gem->pci_device) &&
bufmgr_gem->gtt_size > 256*1024*1024) {
@@ -2811,6 +3105,10 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
bufmgr_gem->has_relaxed_fencing = ret == 0;
+ gp.param = I915_PARAM_HAS_WAIT_TIMEOUT;
+ ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+ bufmgr_gem->has_wait_timeout = ret == 0;
+
gp.param = I915_PARAM_HAS_LLC;
ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
if (ret != 0) {
@@ -2820,7 +3118,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) |
IS_GEN7(bufmgr_gem->pci_device));
} else
- bufmgr_gem->has_llc = ret == 0;
+ bufmgr_gem->has_llc = *gp.value;
if (bufmgr_gem->gen < 4) {
gp.param = I915_PARAM_NUM_FENCES_AVAIL;
diff --git a/intel/intel_bufmgr_priv.h b/intel/intel_bufmgr_priv.h
index 0b62520..2592d42 100644
--- a/intel/intel_bufmgr_priv.h
+++ b/intel/intel_bufmgr_priv.h
@@ -280,6 +280,11 @@ struct _drm_intel_bufmgr {
int debug;
};
+struct _drm_intel_context {
+ unsigned int ctx_id;
+ struct _drm_intel_bufmgr *bufmgr;
+};
+
#define ALIGN(value, alignment) ((value + alignment - 1) & ~(alignment - 1))
#define ROUND_UP_TO(x, y) (((x) + (y) - 1) / (y) * (y))
#define ROUND_UP_TO_MB(x) ROUND_UP_TO((x), 1024*1024)
diff --git a/intel/intel_chipset.h b/intel/intel_chipset.h
index 435d01a..a2eb894 100644
--- a/intel/intel_chipset.h
+++ b/intel/intel_chipset.h
@@ -44,12 +44,46 @@
#define PCI_CHIP_IVYBRIDGE_M_GT1 0x0156 /* mobile */
#define PCI_CHIP_IVYBRIDGE_M_GT2 0x0166
#define PCI_CHIP_IVYBRIDGE_S 0x015a /* server */
+#define PCI_CHIP_IVYBRIDGE_S_GT2 0x016a /* server */
#define PCI_CHIP_HASWELL_GT1 0x0402 /* Desktop */
#define PCI_CHIP_HASWELL_GT2 0x0412
+#define PCI_CHIP_HASWELL_GT2_PLUS 0x0422
#define PCI_CHIP_HASWELL_M_GT1 0x0406 /* Mobile */
#define PCI_CHIP_HASWELL_M_GT2 0x0416
-#define PCI_CHIP_HASWELL_M_ULT_GT2 0x0A16 /* Mobile ULT */
+#define PCI_CHIP_HASWELL_M_GT2_PLUS 0x0426
+#define PCI_CHIP_HASWELL_S_GT1 0x040A /* Server */
+#define PCI_CHIP_HASWELL_S_GT2 0x041A
+#define PCI_CHIP_HASWELL_S_GT2_PLUS 0x042A
+#define PCI_CHIP_HASWELL_SDV_GT1 0x0C02 /* Desktop */
+#define PCI_CHIP_HASWELL_SDV_GT2 0x0C12
+#define PCI_CHIP_HASWELL_SDV_GT2_PLUS 0x0C22
+#define PCI_CHIP_HASWELL_SDV_M_GT1 0x0C06 /* Mobile */
+#define PCI_CHIP_HASWELL_SDV_M_GT2 0x0C16
+#define PCI_CHIP_HASWELL_SDV_M_GT2_PLUS 0x0C26
+#define PCI_CHIP_HASWELL_SDV_S_GT1 0x0C0A /* Server */
+#define PCI_CHIP_HASWELL_SDV_S_GT2 0x0C1A
+#define PCI_CHIP_HASWELL_SDV_S_GT2_PLUS 0x0C2A
+#define PCI_CHIP_HASWELL_ULT_GT1 0x0A02 /* Desktop */
+#define PCI_CHIP_HASWELL_ULT_GT2 0x0A12
+#define PCI_CHIP_HASWELL_ULT_GT2_PLUS 0x0A22
+#define PCI_CHIP_HASWELL_ULT_M_GT1 0x0A06 /* Mobile */
+#define PCI_CHIP_HASWELL_ULT_M_GT2 0x0A16
+#define PCI_CHIP_HASWELL_ULT_M_GT2_PLUS 0x0A26
+#define PCI_CHIP_HASWELL_ULT_S_GT1 0x0A0A /* Server */
+#define PCI_CHIP_HASWELL_ULT_S_GT2 0x0A1A
+#define PCI_CHIP_HASWELL_ULT_S_GT2_PLUS 0x0A2A
+#define PCI_CHIP_HASWELL_CRW_GT1 0x0D12 /* Desktop */
+#define PCI_CHIP_HASWELL_CRW_GT2 0x0D22
+#define PCI_CHIP_HASWELL_CRW_GT2_PLUS 0x0D32
+#define PCI_CHIP_HASWELL_CRW_M_GT1 0x0D16 /* Mobile */
+#define PCI_CHIP_HASWELL_CRW_M_GT2 0x0D26
+#define PCI_CHIP_HASWELL_CRW_M_GT2_PLUS 0x0D36
+#define PCI_CHIP_HASWELL_CRW_S_GT1 0x0D1A /* Server */
+#define PCI_CHIP_HASWELL_CRW_S_GT2 0x0D2A
+#define PCI_CHIP_HASWELL_CRW_S_GT2_PLUS 0x0D3A
+
+#define PCI_CHIP_VALLEYVIEW_PO 0x0f30 /* power on board */
#define IS_830(dev) (dev == 0x3577)
#define IS_845(dev) (dev == 0x2562)
@@ -90,6 +124,8 @@
#define IS_I965GM(dev) (dev == 0x2A02)
+#define IS_VALLEYVIEW(dev) (dev == 0xf30)
+
#define IS_GEN4(dev) (dev == 0x2972 || \
dev == 0x2982 || \
dev == 0x2992 || \
@@ -122,19 +158,52 @@
dev == PCI_CHIP_SANDYBRIDGE_S)
#define IS_GEN7(devid) (IS_IVYBRIDGE(devid) || \
- IS_HASWELL(devid))
+ IS_HASWELL(devid) || \
+ IS_VALLEYVIEW(devid))
#define IS_IVYBRIDGE(dev) (dev == PCI_CHIP_IVYBRIDGE_GT1 || \
dev == PCI_CHIP_IVYBRIDGE_GT2 || \
dev == PCI_CHIP_IVYBRIDGE_M_GT1 || \
dev == PCI_CHIP_IVYBRIDGE_M_GT2 || \
- dev == PCI_CHIP_IVYBRIDGE_S)
+ dev == PCI_CHIP_IVYBRIDGE_S || \
+ dev == PCI_CHIP_IVYBRIDGE_S_GT2)
#define IS_HSW_GT1(devid) (devid == PCI_CHIP_HASWELL_GT1 || \
- devid == PCI_CHIP_HASWELL_M_GT1)
+ devid == PCI_CHIP_HASWELL_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_S_GT1 || \
+ devid == PCI_CHIP_HASWELL_SDV_GT1 || \
+ devid == PCI_CHIP_HASWELL_SDV_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_SDV_S_GT1 || \
+ devid == PCI_CHIP_HASWELL_ULT_GT1 || \
+ devid == PCI_CHIP_HASWELL_ULT_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_ULT_S_GT1 || \
+ devid == PCI_CHIP_HASWELL_CRW_GT1 || \
+ devid == PCI_CHIP_HASWELL_CRW_M_GT1 || \
+ devid == PCI_CHIP_HASWELL_CRW_S_GT1)
#define IS_HSW_GT2(devid) (devid == PCI_CHIP_HASWELL_GT2 || \
devid == PCI_CHIP_HASWELL_M_GT2 || \
- devid == PCI_CHIP_HASWELL_M_ULT_GT2)
+ devid == PCI_CHIP_HASWELL_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_SDV_GT2 || \
+ devid == PCI_CHIP_HASWELL_SDV_M_GT2 || \
+ devid == PCI_CHIP_HASWELL_SDV_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_ULT_GT2 || \
+ devid == PCI_CHIP_HASWELL_ULT_M_GT2 || \
+ devid == PCI_CHIP_HASWELL_ULT_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_CRW_GT2 || \
+ devid == PCI_CHIP_HASWELL_CRW_M_GT2 || \
+ devid == PCI_CHIP_HASWELL_CRW_S_GT2 || \
+ devid == PCI_CHIP_HASWELL_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_S_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_SDV_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_SDV_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_SDV_S_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_ULT_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_ULT_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_ULT_S_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_CRW_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_CRW_M_GT2_PLUS || \
+ devid == PCI_CHIP_HASWELL_CRW_S_GT2_PLUS)
#define IS_HASWELL(devid) (IS_HSW_GT1(devid) || \
IS_HSW_GT2(devid))
diff --git a/intel/intel_decode.c b/intel/intel_decode.c
index df9b704..a4b045a 100644
--- a/intel/intel_decode.c
+++ b/intel/intel_decode.c
@@ -139,6 +139,90 @@ instr_out(struct drm_intel_decode *ctx, unsigned int index,
}
static int
+decode_MI_SET_CONTEXT(struct drm_intel_decode *ctx)
+{
+ uint32_t data = ctx->data[1];
+ if (ctx->gen > 7)
+ return 1;
+
+ instr_out(ctx, 0, "MI_SET_CONTEXT\n");
+ instr_out(ctx, 1, "gtt offset = 0x%x%s%s\n",
+ data & ~0xfff,
+ data & (1<<1)? ", Force Restore": "",
+ data & (1<<0)? ", Restore Inhibit": "");
+
+ return 2;
+}
+
+static int
+decode_MI_WAIT_FOR_EVENT(struct drm_intel_decode *ctx)
+{
+ const char *cc_wait;
+ int cc_shift = 0;
+ uint32_t data = ctx->data[0];
+
+ if (ctx->gen <= 5)
+ cc_shift = 9;
+ else
+ cc_shift = 16;
+
+ switch ((data >> cc_shift) & 0x1f) {
+ case 1:
+ cc_wait = ", cc wait 1";
+ break;
+ case 2:
+ cc_wait = ", cc wait 2";
+ break;
+ case 3:
+ cc_wait = ", cc wait 3";
+ break;
+ case 4:
+ cc_wait = ", cc wait 4";
+ break;
+ case 5:
+ cc_wait = ", cc wait 4";
+ break;
+ default:
+ cc_wait = "";
+ break;
+ }
+
+ if (ctx->gen <= 5) {
+ instr_out(ctx, 0, "MI_WAIT_FOR_EVENT%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ data & (1<<18)? ", pipe B start vblank wait": "",
+ data & (1<<17)? ", pipe A start vblank wait": "",
+ data & (1<<16)? ", overlay flip pending wait": "",
+ data & (1<<14)? ", pipe B hblank wait": "",
+ data & (1<<13)? ", pipe A hblank wait": "",
+ cc_wait,
+ data & (1<<8)? ", plane C pending flip wait": "",
+ data & (1<<7)? ", pipe B vblank wait": "",
+ data & (1<<6)? ", plane B pending flip wait": "",
+ data & (1<<5)? ", pipe B scan line wait": "",
+ data & (1<<4)? ", fbc idle wait": "",
+ data & (1<<3)? ", pipe A vblank wait": "",
+ data & (1<<2)? ", plane A pending flip wait": "",
+ data & (1<<1)? ", plane A scan line wait": "");
+ } else {
+ instr_out(ctx, 0, "MI_WAIT_FOR_EVENT%s%s%s%s%s%s%s%s%s%s%s%s\n",
+ data & (1<<20)? ", sprite C pending flip wait": "", /* ivb */
+ cc_wait,
+ data & (1<<13)? ", pipe B hblank wait": "",
+ data & (1<<11)? ", pipe B vblank wait": "",
+ data & (1<<10)? ", sprite B pending flip wait": "",
+ data & (1<<9)? ", plane B pending flip wait": "",
+ data & (1<<8)? ", plane B scan line wait": "",
+ data & (1<<5)? ", pipe A hblank wait": "",
+ data & (1<<3)? ", pipe A vblank wait": "",
+ data & (1<<2)? ", sprite A pending flip wait": "",
+ data & (1<<1)? ", plane A pending flip wait": "",
+ data & (1<<0)? ", plane A scan line wait": "");
+ }
+
+ return 1;
+}
+
+static int
decode_mi(struct drm_intel_decode *ctx)
{
unsigned int opcode, len = -1;
@@ -151,6 +235,7 @@ decode_mi(struct drm_intel_decode *ctx)
unsigned int min_len;
unsigned int max_len;
const char *name;
+ int (*func)(struct drm_intel_decode *ctx);
} opcodes_mi[] = {
{ 0x08, 0, 1, 1, "MI_ARB_ON_OFF" },
{ 0x0a, 0, 1, 1, "MI_BATCH_BUFFER_END" },
@@ -164,16 +249,16 @@ decode_mi(struct drm_intel_decode *ctx)
{ 0x00, 0, 1, 1, "MI_NOOP" },
{ 0x11, 0x3f, 2, 2, "MI_OVERLAY_FLIP" },
{ 0x07, 0, 1, 1, "MI_REPORT_HEAD" },
- { 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT" },
+ { 0x18, 0x3f, 2, 2, "MI_SET_CONTEXT", decode_MI_SET_CONTEXT },
{ 0x20, 0x3f, 3, 4, "MI_STORE_DATA_IMM" },
{ 0x21, 0x3f, 3, 4, "MI_STORE_DATA_INDEX" },
{ 0x24, 0x3f, 3, 3, "MI_STORE_REGISTER_MEM" },
{ 0x02, 0, 1, 1, "MI_USER_INTERRUPT" },
- { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT" },
+ { 0x03, 0, 1, 1, "MI_WAIT_FOR_EVENT", decode_MI_WAIT_FOR_EVENT },
{ 0x16, 0x7f, 3, 3, "MI_SEMAPHORE_MBOX" },
{ 0x26, 0x1f, 3, 4, "MI_FLUSH_DW" },
{ 0x0b, 0, 1, 1, "MI_SUSPEND_FLUSH"},
- };
+ }, *opcode_mi = NULL;
/* check instruction length */
for (opcode = 0; opcode < sizeof(opcodes_mi) / sizeof(opcodes_mi[0]);
@@ -192,10 +277,14 @@ decode_mi(struct drm_intel_decode *ctx)
opcodes_mi[opcode].max_len);
}
}
+ opcode_mi = &opcodes_mi[opcode];
break;
}
}
+ if (opcode_mi && opcode_mi->func)
+ return opcode_mi->func(ctx);
+
switch ((data[0] & 0x1f800000) >> 23) {
case 0x0a:
instr_out(ctx, 0, "MI_BATCH_BUFFER_END\n");
@@ -1625,7 +1714,7 @@ decode_3d_1d(struct drm_intel_decode *ctx)
}
} else {
instr_out(ctx, i,
- "S%d: 0x%08x\n", i, data[i]);
+ "S%d: 0x%08x\n", word, data[i]);
}
i++;
}
@@ -3115,6 +3204,8 @@ decode_3d_965(struct drm_intel_decode *ctx)
{ 0x7829, 0x00ff, 2, 2, "3DSTATE_BINDING_TABLE_POINTERS_GS" },
{ 0x782a, 0x00ff, 2, 2, "3DSTATE_BINDING_TABLE_POINTERS_PS" },
{ 0x782b, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_VS" },
+ { 0x782c, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_HS" },
+ { 0x782d, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_DS" },
{ 0x782e, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_GS" },
{ 0x782f, 0x00ff, 2, 2, "3DSTATE_SAMPLER_STATE_POINTERS_PS" },
{ 0x7830, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_URB_VS },
@@ -3135,6 +3226,9 @@ decode_3d_965(struct drm_intel_decode *ctx)
{ 0x790d, 0xffff, 4, 4, "3DSTATE_MULTISAMPLE", 7 },
{ 0x7910, 0xffff, 2, 2, "3DSTATE_CLEAR_PARAMS" },
{ 0x7912, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_VS" },
+ { 0x7913, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_HS" },
+ { 0x7914, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_DS" },
+ { 0x7915, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_GS" },
{ 0x7916, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_PS" },
{ 0x7917, 0x00ff, 2, 2+128*2, "3DSTATE_SO_DECL_LIST" },
{ 0x7918, 0x00ff, 4, 4, "3DSTATE_SO_BUFFER" },
@@ -3312,8 +3406,8 @@ decode_3d_965(struct drm_intel_decode *ctx)
instr_out(ctx, i,
"buffer %d: %svalid, type 0x%04x, "
"src offset 0x%04x bytes\n",
- data[i] >> (IS_GEN6(devid) ? 26 : 27),
- data[i] & (1 << (IS_GEN6(devid) ? 25 : 26)) ?
+ data[i] >> ((IS_GEN6(devid) || IS_GEN7(devid)) ? 26 : 27),
+ data[i] & (1 << ((IS_GEN6(devid) || IS_GEN7(devid)) ? 25 : 26)) ?
"" : "in", (data[i] >> 16) & 0x1ff,
data[i] & 0x07ff);
i++;
diff --git a/intel/test_decode.c b/intel/test_decode.c
index c9ab7ad..0fcdf3b 100644
--- a/intel/test_decode.c
+++ b/intel/test_decode.c
@@ -21,6 +21,8 @@
* IN THE SOFTWARE.
*/
+#define _GNU_SOURCE
+
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
diff --git a/intel/tests/gen7-3d.batch-ref.txt b/intel/tests/gen7-3d.batch-ref.txt
index be3c85e..cd2dfc4 100644
diff --git a/libdrm_lists.h b/libdrm_lists.h
index 6410f57..8926d8d 100644
--- a/libdrm_lists.h
+++ b/libdrm_lists.h
@@ -78,6 +78,13 @@ typedef struct _drmMMListHead
#define DRMLISTEMPTY(__item) ((__item)->next == (__item))
+#define DRMLISTSINGLE(__list) \
+ (!DRMLISTEMPTY(__list) && ((__list)->next == (__list)->prev))
+
+#define DRMLISTFOREACH(__item, __list) \
+ for ((__item) = (__list)->next; \
+ (__item) != (__list); (__item) = (__item)->next)
+
#define DRMLISTFOREACHSAFE(__item, __temp, __list) \
for ((__item) = (__list)->next, (__temp) = (__item)->next; \
(__item) != (__list); \
@@ -87,3 +94,25 @@ typedef struct _drmMMListHead
for ((__item) = (__list)->prev, (__temp) = (__item)->prev; \
(__item) != (__list); \
(__item) = (__temp), (__temp) = (__item)->prev)
+
+#define DRMLISTFOREACHENTRY(__item, __list, __head) \
+ for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head); \
+ &(__item)->__head != (__list); \
+ (__item) = DRMLISTENTRY(typeof(*__item), \
+ (__item)->__head.next, __head))
+
+#define DRMLISTFOREACHENTRYSAFE(__item, __temp, __list, __head) \
+ for ((__item) = DRMLISTENTRY(typeof(*__item), (__list)->next, __head), \
+ (__temp) = DRMLISTENTRY(typeof(*__item), \
+ (__item)->__head.next, __head); \
+ &(__item)->__head != (__list); \
+ (__item) = (__temp), \
+ (__temp) = DRMLISTENTRY(typeof(*__item), \
+ (__temp)->__head.next, __head))
+
+#define DRMLISTJOIN(__list, __join) if (!DRMLISTEMPTY(__list)) { \
+ (__list)->next->prev = (__join); \
+ (__list)->prev->next = (__join)->next; \
+ (__join)->next->prev = (__list)->prev; \
+ (__join)->next = (__list)->next; \
+}
diff --git a/libkms/Makefile.am b/libkms/Makefile.am
index fa379a4..215450a 100644
--- a/libkms/Makefile.am
+++ b/libkms/Makefile.am
@@ -6,7 +6,7 @@ AM_CFLAGS = \
libkms_la_LTLIBRARIES = libkms.la
libkms_ladir = $(libdir)
libkms_la_LDFLAGS = -version-number 1:0:0 -no-undefined
-libkms_la_LIBADD =
+libkms_la_LIBADD = ../libdrm.la
#if HAVE_LIBUDEV
#libkms_la_LIBADD += $(LIBUDEV_LIBS)
diff --git a/man/Makefile.am b/man/Makefile.am
new file mode 100644
index 0000000..ccd6545
--- /dev/null
+++ b/man/Makefile.am
@@ -0,0 +1,11 @@
+libmandir = $(LIB_MAN_DIR)
+libman_PRE = drmAvailable.man \
+ drmHandleEvent.man \
+ drmModeGetResources.man
+libman_DATA = $(libman_PRE:man=@LIB_MAN_SUFFIX@)
+EXTRA_DIST = $(libman_PRE)
+CLEANFILES = $(libman_DATA)
+SUFFIXES = .$(LIB_MAN_SUFFIX) .man
+
+.man.$(LIB_MAN_SUFFIX):
+ $(AM_V_GEN)$(SED) $(MAN_SUBSTS) < $< > $@
diff --git a/man/drmAvailable.man b/man/drmAvailable.man
new file mode 100644
index 0000000..e1bb8dc
--- /dev/null
+++ b/man/drmAvailable.man
@@ -0,0 +1,25 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH drmAvailable __drivermansuffix__ __vendorversion__
+.SH NAME
+drmAvailable \- determine whether a DRM kernel driver has been loaded
+.SH SYNOPSIS
+.nf
+.B "#include <xf86drm.h>"
+
+.B "int drmAvailable(void);"
+.fi
+.SH DESCRIPTION
+This function allows the caller to determine whether a kernel DRM driver is
+loaded.
+
+.SH RETURN VALUE
+If a DRM driver is currently loaded, this function returns 1. Otherwise 0
+is returned.
+
+.SH REPORTING BUGS
+Bugs in this function should be reported to http://bugs.freedesktop.org under
+the "Mesa" product, with "Other" or "libdrm" as the component.
+
+.SH "SEE ALSO"
+drmOpen(__libmansuffix__)
diff --git a/man/drmHandleEvent.man b/man/drmHandleEvent.man
new file mode 100644
index 0000000..b98f417
--- /dev/null
+++ b/man/drmHandleEvent.man
@@ -0,0 +1,45 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH drmHandleEvent __drivermansuffix__ __vendorversion__
+.SH NAME
+drmHandleEvent \- read and process pending DRM events
+.SH SYNOPSIS
+.nf
+.B "#include <xf86drm.h>"
+
+.B "typedef struct _drmEventContext {"
+.BI " int version;"
+.BI " void (*vblank_handler)(int fd,"
+.BI " unsigned int sequence,"
+.BI " unsigned int tv_sec,"
+.BI " unsigned int tv_usec,"
+.BI " void *user_data);"
+.BI " void (*page_flip_handler)(int fd,"
+.BI " unsigned int sequence,"
+.BI " unsigned int tv_sec,"
+.BI " unsigned int tv_usec,"
+.BI " void *user_data);"
+.B "} drmEventContext, *drmEventContextPtr;"
+
+.B "int drmHandleEvent(int fd, drmEventContextPtr evctx);"
+.fi
+.SH DESCRIPTION
+This function will process outstanding DRM events on
+.I fd
+, which must be an open DRM device. This function should be called after
+the DRM file descriptor has polled readable; it will read the events and
+use the passed-in
+.I evctx
+structure to call function pointers with the parameters noted above.
+
+.SH RETURN VALUE
+Returns 0 on success, or if there is no data to read from the file descriptor.
+Returns -1 if the read on the file descriptor fails or returns less than a
+full event record.
+
+.SH REPORTING BUGS
+Bugs in this function should be reported to http://bugs.freedesktop.org under
+the "Mesa" product, with "Other" or "libdrm" as the component.
+
+.SH "SEE ALSO"
+drmModePageFlip(__libmansuffix__), drmWaitVBlank(__libmansuffix__)
diff --git a/man/drmModeGetResources.man b/man/drmModeGetResources.man
new file mode 100644
index 0000000..369bf7d
--- /dev/null
+++ b/man/drmModeGetResources.man
@@ -0,0 +1,79 @@
+.\" shorthand for double quote that works everywhere.
+.ds q \N'34'
+.TH drmModeGetResources __drivermansuffix__ __vendorversion__
+.SH NAME
+drmModeGetResources \- retrieve current display configuration information
+.SH SYNOPSIS
+.nf
+.B "#include <xf86drmMode.h>"
+
+.BI "typedef struct _drmModeRes {"
+
+.BI " int count_fbs;"
+.BI " uint32_t *fbs;"
+
+.BI " int count_crtcs;"
+.BI " uint32_t *crtcs;"
+
+.BI " int count_connectors;"
+.BI " uint32_t *connectors;"
+
+.BI " int count_encoders;"
+.BI " uint32_t *encoders;"
+
+.BI " uint32_t min_width, max_width;"
+.BI " uint32_t min_height, max_height;"
+.B "} drmModeRes, *drmModeResPtr;"
+
+.B "drmModeResPtr drmModeGetResources(int fd);"
+.fi
+.SH DESCRIPTION
+This function will allocate, populate, and return a drmModeRes structure
+containing information about the current display configuration.
+
+The
+.I count_fbs
+and
+.I fbs
+fields indicate the number of currently allocated framebuffer objects (i.e.
+objects that can be attached to a given CRTC or sprite for display).
+
+The
+.I count_crtcs
+and
+.I crtcs
+fields list the available CRTCs in the configuration. A CRTC is simply
+an object that can scan out a framebuffer to a display sink, and contains
+mode timing and relative position information. CRTCs drive encoders, which
+are responsible for converting the pixel stream into a specific display
+protocol (e.g. MIPI or HDMI).
+
+The
+.I count_connectors
+and
+.I connectors
+fields list the available physical connectors on the system. Note that
+some of these may not be exposed from the chassis (e.g. LVDS or eDP).
+Connectors are attached to encoders and contain information about the
+attached display sink (e.g. width and height in mm, subpixel ordering, and
+various other properties).
+
+The
+.I count_encoders
+and
+.I encoders
+fields list the available encoders on the device. Each encoder may be
+associated with a CRTC, and may be used to drive a particular encoder.
+
+The min and max height fields indicate the maximum size of a framebuffer
+for this device (i.e. the scanout size limit).
+
+.SH RETURN VALUE
+Returns a drmModeRes structure pointer on success, 0 on failure.
+
+.SH REPORTING BUGS
+Bugs in this function should be reported to http://bugs.freedesktop.org under
+the "Mesa" product, with "Other" or "libdrm" as the component.
+
+.SH "SEE ALSO"
+drmModeGetFB(__libmansuffix__), drmModeAddFB(__libmansuffix__), drmModeAddFB2(__libmansuffix__), drmModeRmFB(__libmansuffix__), drmModeDirtyFB(__libmansuffix__), drmModeGetCrtc(__libmansuffix__), drmModeSetCrtc(__libmansuffix__), drmModeGetEncoder(__libmansuffix__), drmModeGetConnector(__libmansuffix__)
diff --git a/nouveau/Makefile.am b/nouveau/Makefile.am
index 8b89916..206e892 100644
diff --git a/nouveau/abi16.c b/nouveau/abi16.c
new file mode 100644
index 0000000..a67fbc1
diff --git a/nouveau/bufctx.c b/nouveau/bufctx.c
new file mode 100644
index 0000000..23d6f09
diff --git a/nouveau/libdrm_nouveau.pc.in b/nouveau/libdrm_nouveau.pc.in
index c78a28a..6170613 100644
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
new file mode 100644
index 0000000..940d933
diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
new file mode 100644
index 0000000..c42eea7
diff --git a/nouveau/nouveau_bo.c b/nouveau/nouveau_bo.c
deleted file mode 100644
index d6bb22d..0000000
diff --git a/nouveau/nouveau_bo.h b/nouveau/nouveau_bo.h
deleted file mode 100644
index 3a1f2d4..0000000
diff --git a/nouveau/nouveau_channel.c b/nouveau/nouveau_channel.c
deleted file mode 100644
index 96fa03b..0000000
diff --git a/nouveau/nouveau_channel.h b/nouveau/nouveau_channel.h
deleted file mode 100644
index d61a4c0..0000000
diff --git a/nouveau/nouveau_device.c b/nouveau/nouveau_device.c
deleted file mode 100644
index 425c5d2..0000000
diff --git a/nouveau/nouveau_device.h b/nouveau/nouveau_device.h
deleted file mode 100644
index c0d9333..0000000
diff --git a/nouveau/nouveau_drmif.h b/nouveau/nouveau_drmif.h
deleted file mode 100644
index ec226a2..0000000
diff --git a/nouveau/nouveau_grobj.c b/nouveau/nouveau_grobj.c
deleted file mode 100644
index 36344b9..0000000
diff --git a/nouveau/nouveau_grobj.h b/nouveau/nouveau_grobj.h
deleted file mode 100644
index 51ac7d9..0000000
diff --git a/nouveau/nouveau_notifier.c b/nouveau/nouveau_notifier.c
deleted file mode 100644
index 513fa63..0000000
diff --git a/nouveau/nouveau_notifier.h b/nouveau/nouveau_notifier.h
deleted file mode 100644
index dbc6a3b..0000000
diff --git a/nouveau/nouveau_private.h b/nouveau/nouveau_private.h
deleted file mode 100644
index 124fe87..0000000
diff --git a/nouveau/nouveau_pushbuf.c b/nouveau/nouveau_pushbuf.c
deleted file mode 100644
index 59f60d9..0000000
diff --git a/nouveau/nouveau_pushbuf.h b/nouveau/nouveau_pushbuf.h
deleted file mode 100644
index 2a98789..0000000
diff --git a/nouveau/nouveau_reloc.c b/nouveau/nouveau_reloc.c
deleted file mode 100644
index cd219db..0000000
diff --git a/nouveau/nouveau_reloc.h b/nouveau/nouveau_reloc.h
deleted file mode 100644
index 24ddb52..0000000
diff --git a/nouveau/nouveau_resource.c b/nouveau/nouveau_resource.c
deleted file mode 100644
index 7acaf7d..0000000
diff --git a/nouveau/nouveau_resource.h b/nouveau/nouveau_resource.h
deleted file mode 100644
index b760dfb..0000000
diff --git a/nouveau/nv04_pushbuf.h b/nouveau/nv04_pushbuf.h
deleted file mode 100644
index 586b284..0000000
diff --git a/nouveau/nvc0_pushbuf.h b/nouveau/nvc0_pushbuf.h
deleted file mode 100644
index 40dc7e6..0000000
diff --git a/nouveau/private.h b/nouveau/private.h
new file mode 100644
index 0000000..b409cc8
diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c
new file mode 100644
index 0000000..0e37ce3
diff --git a/omap/omap_drm.c b/omap/omap_drm.c
index e611806..89f1491 100644
--- a/omap/omap_drm.c
+++ b/omap/omap_drm.c
@@ -32,10 +32,15 @@
#include <stdlib.h>
#include <linux/stddef.h>
+#include <linux/types.h>
#include <errno.h>
#include <sys/mman.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <pthread.h>
#include <xf86drm.h>
+#include <xf86atomic.h>
#include "omap_drm.h"
#include "omap_drmif.h"
@@ -44,8 +49,23 @@
#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
#define PAGE_SIZE 4096
+static pthread_mutex_t table_lock = PTHREAD_MUTEX_INITIALIZER;
+static void * dev_table;
+
struct omap_device {
int fd;
+ atomic_t refcnt;
+
+ /* The handle_table is used to track GEM bo handles associated w/
+ * this fd. This is needed, in particular, when importing
+ * dmabuf's because we don't want multiple 'struct omap_bo's
+ * floating around with the same handle. Otherwise, when the
+ * first one is omap_bo_del()'d the handle becomes no longer
+ * valid, and the remaining 'struct omap_bo's are left pointing
+ * to an invalid handle (and possible a GEM bo that is already
+ * free'd).
+ */
+ void *handle_table;
};
/* a GEM buffer object allocated from the DRM device */
@@ -56,19 +76,58 @@ struct omap_bo {
uint32_t handle;
uint32_t name; /* flink global handle (DRI2 name) */
uint64_t offset; /* offset to mmap() */
+ int fd; /* dmabuf handle */
+ atomic_t refcnt;
};
-struct omap_device * omap_device_new(int fd)
+static struct omap_device * omap_device_new_impl(int fd)
{
struct omap_device *dev = calloc(sizeof(*dev), 1);
if (!dev)
return NULL;
dev->fd = fd;
+ atomic_set(&dev->refcnt, 1);
+ dev->handle_table = drmHashCreate();
+ return dev;
+}
+
+struct omap_device * omap_device_new(int fd)
+{
+ struct omap_device *dev = NULL;
+
+ pthread_mutex_lock(&table_lock);
+
+ if (!dev_table)
+ dev_table = drmHashCreate();
+
+ if (drmHashLookup(dev_table, fd, (void **)&dev)) {
+ /* not found, create new device */
+ dev = omap_device_new_impl(fd);
+ drmHashInsert(dev_table, fd, dev);
+ } else {
+ /* found, just incr refcnt */
+ dev = omap_device_ref(dev);
+ }
+
+ pthread_mutex_unlock(&table_lock);
+
+ return dev;
+}
+
+struct omap_device * omap_device_ref(struct omap_device *dev)
+{
+ atomic_inc(&dev->refcnt);
return dev;
}
void omap_device_del(struct omap_device *dev)
{
+ if (!atomic_dec_and_test(&dev->refcnt))
+ return;
+ pthread_mutex_lock(&table_lock);
+ drmHashDestroy(dev->handle_table);
+ drmHashDelete(dev_table, dev->fd);
+ pthread_mutex_unlock(&table_lock);
free(dev);
}
@@ -98,11 +157,43 @@ int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value)
return drmCommandWrite(dev->fd, DRM_OMAP_SET_PARAM, &req, sizeof(req));
}
+/* lookup a buffer from it's handle, call w/ table_lock held: */
+static struct omap_bo * lookup_bo(struct omap_device *dev,
+ uint32_t handle)
+{
+ struct omap_bo *bo = NULL;
+ if (!drmHashLookup(dev->handle_table, handle, (void **)&bo)) {
+ /* found, incr refcnt and return: */
+ bo = omap_bo_ref(bo);
+ }
+ return bo;
+}
+
+/* allocate a new buffer object, call w/ table_lock held */
+static struct omap_bo * bo_from_handle(struct omap_device *dev,
+ uint32_t handle)
+{
+ struct omap_bo *bo = calloc(sizeof(*bo), 1);
+ if (!bo) {
+ struct drm_gem_close req = {
+ .handle = handle,
+ };
+ drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+ return NULL;
+ }
+ bo->dev = omap_device_ref(dev);
+ bo->handle = handle;
+ atomic_set(&bo->refcnt, 1);
+ /* add ourselves to the handle table: */
+ drmHashInsert(dev->handle_table, handle, bo);
+ return bo;
+}
+
/* allocate a new buffer object */
static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
union omap_gem_size size, uint32_t flags)
{
- struct omap_bo *bo;
+ struct omap_bo *bo = NULL;
struct drm_omap_gem_new req = {
.size = size,
.flags = flags,
@@ -112,12 +203,13 @@ static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
goto fail;
}
- bo = calloc(sizeof(*bo), 1);
- if (!bo) {
+ if (drmCommandWriteRead(dev->fd, DRM_OMAP_GEM_NEW, &req, sizeof(req))) {
goto fail;
}
- bo->dev = dev;
+ pthread_mutex_lock(&table_lock);
+ bo = bo_from_handle(dev, req.handle);
+ pthread_mutex_unlock(&table_lock);
if (flags & OMAP_BO_TILED) {
bo->size = round_up(size.tiled.width, PAGE_SIZE) * size.tiled.height;
@@ -125,12 +217,6 @@ static struct omap_bo * omap_bo_new_impl(struct omap_device *dev,
bo->size = size.bytes;
}
- if (drmCommandWriteRead(dev->fd, DRM_OMAP_GEM_NEW, &req, sizeof(req))) {
- goto fail;
- }
-
- bo->handle = req.handle;
-
return bo;
fail:
@@ -168,6 +254,12 @@ struct omap_bo * omap_bo_new_tiled(struct omap_device *dev,
return omap_bo_new_impl(dev, gsize, flags);
}
+struct omap_bo * omap_bo_ref(struct omap_bo *bo)
+{
+ atomic_inc(&bo->refcnt);
+ return bo;
+}
+
/* get buffer info */
static int get_buffer_info(struct omap_bo *bo)
{
@@ -190,27 +282,63 @@ static int get_buffer_info(struct omap_bo *bo)
/* import a buffer object from DRI2 name */
struct omap_bo * omap_bo_from_name(struct omap_device *dev, uint32_t name)
{
- struct omap_bo *bo;
+ struct omap_bo *bo = NULL;
struct drm_gem_open req = {
.name = name,
};
- bo = calloc(sizeof(*bo), 1);
- if (!bo) {
+ pthread_mutex_lock(&table_lock);
+
+ if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
goto fail;
}
- if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
+ bo = lookup_bo(dev, req.handle);
+ if (!bo) {
+ bo = bo_from_handle(dev, req.handle);
+ bo->name = name;
+ }
+
+ pthread_mutex_unlock(&table_lock);
+
+ return bo;
+
+fail:
+ pthread_mutex_unlock(&table_lock);
+ free(bo);
+ return NULL;
+}
+
+/* import a buffer from dmabuf fd, does not take ownership of the
+ * fd so caller should close() the fd when it is otherwise done
+ * with it (even if it is still using the 'struct omap_bo *')
+ */
+struct omap_bo * omap_bo_from_dmabuf(struct omap_device *dev, int fd)
+{
+ struct omap_bo *bo = NULL;
+ struct drm_prime_handle req = {
+ .fd = fd,
+ };
+ int ret;
+
+ pthread_mutex_lock(&table_lock);
+
+ ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
+ if (ret) {
goto fail;
}
- bo->dev = dev;
- bo->name = name;
- bo->handle = req.handle;
+ bo = lookup_bo(dev, req.handle);
+ if (!bo) {
+ bo = bo_from_handle(dev, req.handle);
+ }
+
+ pthread_mutex_unlock(&table_lock);
return bo;
fail:
+ pthread_mutex_unlock(&table_lock);
free(bo);
return NULL;
}
@@ -222,18 +350,29 @@ void omap_bo_del(struct omap_bo *bo)
return;
}
+ if (!atomic_dec_and_test(&bo->refcnt))
+ return;
+
if (bo->map) {
munmap(bo->map, bo->size);
}
+ if (bo->fd) {
+ close(bo->fd);
+ }
+
if (bo->handle) {
struct drm_gem_close req = {
.handle = bo->handle,
};
-
+ pthread_mutex_lock(&table_lock);
+ drmHashDelete(bo->dev->handle_table, bo->handle);
drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+ pthread_mutex_unlock(&table_lock);
}
+ omap_device_del(bo->dev);
+
free(bo);
}
@@ -264,6 +403,28 @@ uint32_t omap_bo_handle(struct omap_bo *bo)
return bo->handle;
}
+/* caller owns the dmabuf fd that is returned and is responsible
+ * to close() it when done
+ */
+int omap_bo_dmabuf(struct omap_bo *bo)
+{
+ if (!bo->fd) {
+ struct drm_prime_handle req = {
+ .handle = bo->handle,
+ .flags = DRM_CLOEXEC,
+ };
+ int ret;
+
+ ret = drmIoctl(bo->dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
+ if (ret) {
+ return ret;
+ }
+
+ bo->fd = req.fd;
+ }
+ return dup(bo->fd);
+}
+
uint32_t omap_bo_size(struct omap_bo *bo)
{
if (!bo->size) {
diff --git a/omap/omap_drm.h b/omap/omap_drm.h
index f277cea..9c6c0e4 100644
--- a/omap/omap_drm.h
+++ b/omap/omap_drm.h
@@ -1,26 +1,36 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
/*
- * include/drm/omap_drm.h
+ * Copyright (C) 2011 Texas Instruments, Inc
*
- * Copyright (C) 2011 Texas Instruments
- * Author: Rob Clark <rob@ti.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, sublicense,
+ * 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:
*
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 as published by
- * the Free Software Foundation.
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
*
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
+ * 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 NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
*
- * You should have received a copy of the GNU General Public License along with
- * this program. If not, see <http://www.gnu.org/licenses/>.
+ * Authors:
+ * Rob Clark <rob@ti.com>
*/
#ifndef __OMAP_DRM_H__
#define __OMAP_DRM_H__
-#include "drm.h"
+#include <stdint.h>
+#include <drm.h>
/* Please note that modifications to all structs defined here are
* subject to backwards-compatibility constraints.
diff --git a/omap/omap_drmif.h b/omap/omap_drmif.h
index eb75a80..e62d127 100644
--- a/omap/omap_drmif.h
+++ b/omap/omap_drmif.h
@@ -38,6 +38,7 @@ struct omap_device;
*/
struct omap_device * omap_device_new(int fd);
+struct omap_device * omap_device_ref(struct omap_device *dev);
void omap_device_del(struct omap_device *dev);
int omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value);
int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value);
@@ -49,10 +50,13 @@ struct omap_bo * omap_bo_new(struct omap_device *dev,
uint32_t size, uint32_t flags);
struct omap_bo * omap_bo_new_tiled(struct omap_device *dev,
uint32_t width, uint32_t height, uint32_t flags);
+struct omap_bo * omap_bo_ref(struct omap_bo *bo);
struct omap_bo * omap_bo_from_name(struct omap_device *dev, uint32_t name);
+struct omap_bo * omap_bo_from_dmabuf(struct omap_device *dev, int fd);
void omap_bo_del(struct omap_bo *bo);
int omap_bo_get_name(struct omap_bo *bo, uint32_t *name);
uint32_t omap_bo_handle(struct omap_bo *bo);
+int omap_bo_dmabuf(struct omap_bo *bo);
uint32_t omap_bo_size(struct omap_bo *bo);
void * omap_bo_map(struct omap_bo *bo);
int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op);
diff --git a/radeon/Makefile.am b/radeon/Makefile.am
index 37be8cc..a8cd100 100644
--- a/radeon/Makefile.am
+++ b/radeon/Makefile.am
@@ -31,7 +31,7 @@ AM_CFLAGS = \
libdrm_radeon_la_LTLIBRARIES = libdrm_radeon.la
libdrm_radeon_ladir = $(libdir)
-libdrm_radeon_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libdrm_radeon_la_LDFLAGS = -version-number 1:0:1 -no-undefined
libdrm_radeon_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
libdrm_radeon_la_SOURCES = \
diff --git a/radeon/r600_pci_ids.h b/radeon/r600_pci_ids.h
index 8fbd749..b9a85db 100644
--- a/radeon/r600_pci_ids.h
+++ b/radeon/r600_pci_ids.h
@@ -152,10 +152,12 @@ CHIPSET(0x68F1, CEDAR_68F1, CEDAR)
CHIPSET(0x68F2, CEDAR_68F2, CEDAR)
CHIPSET(0x68F8, CEDAR_68F8, CEDAR)
CHIPSET(0x68F9, CEDAR_68F9, CEDAR)
+CHIPSET(0x68FA, CEDAR_68FA, CEDAR)
CHIPSET(0x68FE, CEDAR_68FE, CEDAR)
CHIPSET(0x68C0, REDWOOD_68C0, REDWOOD)
CHIPSET(0x68C1, REDWOOD_68C1, REDWOOD)
+CHIPSET(0x68C7, REDWOOD_68C7, REDWOOD)
CHIPSET(0x68C8, REDWOOD_68C8, REDWOOD)
CHIPSET(0x68C9, REDWOOD_68C9, REDWOOD)
CHIPSET(0x68D8, REDWOOD_68D8, REDWOOD)
@@ -178,6 +180,8 @@ CHIPSET(0x6880, CYPRESS_6880, CYPRESS)
CHIPSET(0x6888, CYPRESS_6888, CYPRESS)
CHIPSET(0x6889, CYPRESS_6889, CYPRESS)
CHIPSET(0x688A, CYPRESS_688A, CYPRESS)
+CHIPSET(0x688C, CYPRESS_688C, CYPRESS)
+CHIPSET(0x688D, CYPRESS_688D, CYPRESS)
CHIPSET(0x6898, CYPRESS_6898, CYPRESS)
CHIPSET(0x6899, CYPRESS_6899, CYPRESS)
CHIPSET(0x689B, CYPRESS_689B, CYPRESS)
@@ -192,6 +196,9 @@ CHIPSET(0x9804, PALM_9804, PALM)
CHIPSET(0x9805, PALM_9805, PALM)
CHIPSET(0x9806, PALM_9806, PALM)
CHIPSET(0x9807, PALM_9807, PALM)
+CHIPSET(0x9808, PALM_9808, PALM)
+CHIPSET(0x9809, PALM_9809, PALM)
+CHIPSET(0x980A, PALM_980A, PALM)
CHIPSET(0x9640, SUMO_9640, SUMO)
CHIPSET(0x9641, SUMO_9641, SUMO)
@@ -201,7 +208,10 @@ CHIPSET(0x9644, SUMO2_9644, SUMO2)
CHIPSET(0x9645, SUMO2_9645, SUMO2)
CHIPSET(0x9647, SUMO_9647, SUMO)
CHIPSET(0x9648, SUMO_9648, SUMO)
+CHIPSET(0x9649, SUMO_9649, SUMO)
CHIPSET(0x964a, SUMO_964A, SUMO)
+CHIPSET(0x964b, SUMO_964B, SUMO)
+CHIPSET(0x964c, SUMO_964C, SUMO)
CHIPSET(0x964e, SUMO_964E, SUMO)
CHIPSET(0x964f, SUMO_964F, SUMO)
@@ -234,6 +244,7 @@ CHIPSET(0x6729, BARTS_6729, BARTS)
CHIPSET(0x6738, BARTS_6738, BARTS)
CHIPSET(0x6739, BARTS_6739, BARTS)
CHIPSET(0x673E, BARTS_673E, BARTS)
+
CHIPSET(0x6740, TURKS_6740, TURKS)
CHIPSET(0x6741, TURKS_6741, TURKS)
CHIPSET(0x6742, TURKS_6742, TURKS)
@@ -244,9 +255,13 @@ CHIPSET(0x6746, TURKS_6746, TURKS)
CHIPSET(0x6747, TURKS_6747, TURKS)
CHIPSET(0x6748, TURKS_6748, TURKS)
CHIPSET(0x6749, TURKS_6749, TURKS)
+CHIPSET(0x674A, TURKS_674A, TURKS)
CHIPSET(0x6750, TURKS_6750, TURKS)
+CHIPSET(0x6751, TURKS_6751, TURKS)
CHIPSET(0x6758, TURKS_6758, TURKS)
CHIPSET(0x6759, TURKS_6759, TURKS)
+CHIPSET(0x675B, TURKS_675B, TURKS)
+CHIPSET(0x675D, TURKS_675D, TURKS)
CHIPSET(0x675F, TURKS_675F, TURKS)
CHIPSET(0x6840, TURKS_6840, TURKS)
CHIPSET(0x6841, TURKS_6841, TURKS)
@@ -267,13 +282,81 @@ CHIPSET(0x6766, CAICOS_6766, CAICOS)
CHIPSET(0x6767, CAICOS_6767, CAICOS)
CHIPSET(0x6768, CAICOS_6768, CAICOS)
CHIPSET(0x6770, CAICOS_6770, CAICOS)
+CHIPSET(0x6771, CAICOS_6771, CAICOS)
+CHIPSET(0x6772, CAICOS_6772, CAICOS)
CHIPSET(0x6778, CAICOS_6778, CAICOS)
CHIPSET(0x6779, CAICOS_6779, CAICOS)
+CHIPSET(0x677B, CAICOS_677B, CAICOS)
CHIPSET(0x9900, ARUBA_9900, ARUBA)
CHIPSET(0x9901, ARUBA_9901, ARUBA)
CHIPSET(0x9903, ARUBA_9903, ARUBA)
CHIPSET(0x9904, ARUBA_9904, ARUBA)
+CHIPSET(0x9905, ARUBA_9905, ARUBA)
+CHIPSET(0x9906, ARUBA_9906, ARUBA)
+CHIPSET(0x9907, ARUBA_9907, ARUBA)
+CHIPSET(0x9908, ARUBA_9908, ARUBA)
+CHIPSET(0x9909, ARUBA_9909, ARUBA)
+CHIPSET(0x990A, ARUBA_990A, ARUBA)
CHIPSET(0x990F, ARUBA_990F, ARUBA)
+CHIPSET(0x9910, ARUBA_9910, ARUBA)
+CHIPSET(0x9913, ARUBA_9913, ARUBA)
+CHIPSET(0x9917, ARUBA_9917, ARUBA)
+CHIPSET(0x9918, ARUBA_9918, ARUBA)
+CHIPSET(0x9919, ARUBA_9919, ARUBA)
CHIPSET(0x9990, ARUBA_9990, ARUBA)
CHIPSET(0x9991, ARUBA_9991, ARUBA)
+CHIPSET(0x9992, ARUBA_9992, ARUBA)
+CHIPSET(0x9993, ARUBA_9993, ARUBA)
+CHIPSET(0x9994, ARUBA_9994, ARUBA)
+CHIPSET(0x99A0, ARUBA_99A0, ARUBA)
+CHIPSET(0x99A2, ARUBA_99A2, ARUBA)
+CHIPSET(0x99A4, ARUBA_99A4, ARUBA)
+
+CHIPSET(0x6780, TAHITI_6780, TAHITI)
+CHIPSET(0x6784, TAHITI_6784, TAHITI)
+CHIPSET(0x6788, TAHITI_6788, TAHITI)
+CHIPSET(0x678A, TAHITI_678A, TAHITI)
+CHIPSET(0x6790, TAHITI_6790, TAHITI)
+CHIPSET(0x6791, TAHITI_6791, TAHITI)
+CHIPSET(0x6792, TAHITI_6792, TAHITI)
+CHIPSET(0x6798, TAHITI_6798, TAHITI)
+CHIPSET(0x6799, TAHITI_6799, TAHITI)
+CHIPSET(0x679A, TAHITI_679A, TAHITI)
+CHIPSET(0x679E, TAHITI_679E, TAHITI)
+CHIPSET(0x679F, TAHITI_679F, TAHITI)
+
+CHIPSET(0x6800, PITCAIRN_6800, PITCAIRN)
+CHIPSET(0x6801, PITCAIRN_6801, PITCAIRN)
+CHIPSET(0x6802, PITCAIRN_6802, PITCAIRN)
+CHIPSET(0x6806, PITCAIRN_6806, PITCAIRN)
+CHIPSET(0x6808, PITCAIRN_6808, PITCAIRN)
+CHIPSET(0x6809, PITCAIRN_6809, PITCAIRN)
+CHIPSET(0x6810, PITCAIRN_6810, PITCAIRN)
+CHIPSET(0x6811, PITCAIRN_6811, PITCAIRN)
+CHIPSET(0x6816, PITCAIRN_6816, PITCAIRN)
+CHIPSET(0x6817, PITCAIRN_6817, PITCAIRN)
+CHIPSET(0x6818, PITCAIRN_6818, PITCAIRN)
+CHIPSET(0x6819, PITCAIRN_6819, PITCAIRN)
+CHIPSET(0x684C, PITCAIRN_684C, PITCAIRN)
+
+CHIPSET(0x6820, VERDE_6820, VERDE)
+CHIPSET(0x6821, VERDE_6821, VERDE)
+CHIPSET(0x6823, VERDE_6823, VERDE)
+CHIPSET(0x6824, VERDE_6824, VERDE)
+CHIPSET(0x6825, VERDE_6825, VERDE)
+CHIPSET(0x6826, VERDE_6826, VERDE)
+CHIPSET(0x6827, VERDE_6827, VERDE)
+CHIPSET(0x6828, VERDE_6828, VERDE)
+CHIPSET(0x6829, VERDE_6829, VERDE)
+CHIPSET(0x682B, VERDE_682B, VERDE)
+CHIPSET(0x682D, VERDE_682D, VERDE)
+CHIPSET(0x682F, VERDE_682F, VERDE)
+CHIPSET(0x6830, VERDE_6830, VERDE)
+CHIPSET(0x6831, VERDE_6831, VERDE)
+CHIPSET(0x6837, VERDE_6837, VERDE)
+CHIPSET(0x6838, VERDE_6838, VERDE)
+CHIPSET(0x6839, VERDE_6839, VERDE)
+CHIPSET(0x683B, VERDE_683B, VERDE)
+CHIPSET(0x683D, VERDE_683D, VERDE)
+CHIPSET(0x683F, VERDE_683F, VERDE)
diff --git a/radeon/radeon_bo_gem.c b/radeon/radeon_bo_gem.c
index 719fba7..265f177 100644
--- a/radeon/radeon_bo_gem.c
+++ b/radeon/radeon_bo_gem.c
@@ -45,7 +45,7 @@
#include "radeon_bo.h"
#include "radeon_bo_int.h"
#include "radeon_bo_gem.h"
-
+#include <fcntl.h>
struct radeon_bo_gem {
struct radeon_bo_int base;
uint32_t name;
@@ -349,3 +349,49 @@ int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t
sizeof(args));
return r;
}
+
+int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle)
+{
+ struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
+ int ret;
+
+ ret = drmPrimeHandleToFD(bo_gem->base.bom->fd, bo->handle, DRM_CLOEXEC, handle);
+ return ret;
+}
+
+struct radeon_bo *radeon_gem_bo_open_prime(struct radeon_bo_manager *bom,
+ int fd_handle,
+ uint32_t size)
+{
+ struct radeon_bo_gem *bo;
+ int r;
+ uint32_t handle;
+
+ bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem));
+ if (bo == NULL) {
+ return NULL;
+ }
+
+ bo->base.bom = bom;
+ bo->base.handle = 0;
+ bo->base.size = size;
+ bo->base.alignment = 0;
+ bo->base.domains = RADEON_GEM_DOMAIN_GTT;
+ bo->base.flags = 0;
+ bo->base.ptr = NULL;
+ atomic_set(&bo->reloc_in_cs, 0);
+ bo->map_count = 0;
+
+ r = drmPrimeFDToHandle(bom->fd, fd_handle, &handle);
+ if (r != 0) {
+ free(bo);
+ return NULL;
+ }
+
+ bo->base.handle = handle;
+ bo->name = handle;
+
+ radeon_bo_ref((struct radeon_bo *)bo);
+ return (struct radeon_bo *)bo;
+
+}
diff --git a/radeon/radeon_bo_gem.h b/radeon/radeon_bo_gem.h
index 0af8610..08965f3 100644
--- a/radeon/radeon_bo_gem.h
+++ b/radeon/radeon_bo_gem.h
@@ -41,4 +41,8 @@ uint32_t radeon_gem_name_bo(struct radeon_bo *bo);
void *radeon_gem_get_reloc_in_cs(struct radeon_bo *bo);
int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain);
int radeon_gem_get_kernel_name(struct radeon_bo *bo, uint32_t *name);
+int radeon_gem_prime_share_bo(struct radeon_bo *bo, int *handle);
+struct radeon_bo *radeon_gem_bo_open_prime(struct radeon_bo_manager *bom,
+ int fd_handle,
+ uint32_t size);
#endif
diff --git a/radeon/radeon_cs_gem.c b/radeon/radeon_cs_gem.c
index 9834bcf..b963140 100644
--- a/radeon/radeon_cs_gem.c
+++ b/radeon/radeon_cs_gem.c
@@ -330,6 +330,7 @@ static int cs_gem_end(struct radeon_cs_int *cs,
return 0;
}
+#if CS_BOF_DUMP
static void cs_gem_dump_bof(struct radeon_cs_int *cs)
{
struct cs_gem *csg = (struct cs_gem*)cs;
@@ -415,6 +416,7 @@ out_err:
bof_decref(device_id);
bof_decref(root);
}
+#endif
static int cs_gem_emit(struct radeon_cs_int *cs)
{
diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
index 6303c47..eb587d2 100644
--- a/radeon/radeon_surface.c
+++ b/radeon/radeon_surface.c
@@ -69,6 +69,9 @@ enum radeon_family {
CHIP_CAICOS,
CHIP_CAYMAN,
CHIP_ARUBA,
+ CHIP_TAHITI,
+ CHIP_PITCAIRN,
+ CHIP_VERDE,
CHIP_LAST,
};
@@ -141,31 +144,32 @@ static unsigned mip_minify(unsigned size, unsigned level)
}
static void surf_minify(struct radeon_surface *surf,
- unsigned level,
+ struct radeon_surface_level *surflevel,
+ unsigned bpe, unsigned level,
uint32_t xalign, uint32_t yalign, uint32_t zalign,
unsigned offset)
{
- surf->level[level].npix_x = mip_minify(surf->npix_x, level);
- surf->level[level].npix_y = mip_minify(surf->npix_y, level);
- surf->level[level].npix_z = mip_minify(surf->npix_z, level);
- surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
- surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
- surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
- if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
- if (surf->level[level].nblk_x < xalign || surf->level[level].nblk_y < yalign) {
- surf->level[level].mode = RADEON_SURF_MODE_1D;
+ surflevel->npix_x = mip_minify(surf->npix_x, level);
+ surflevel->npix_y = mip_minify(surf->npix_y, level);
+ surflevel->npix_z = mip_minify(surf->npix_z, level);
+ surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
+ surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
+ surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
+ if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
+ if (surflevel->nblk_x < xalign || surflevel->nblk_y < yalign) {
+ surflevel->mode = RADEON_SURF_MODE_1D;
return;
}
}
- surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, xalign);
- surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, yalign);
- surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, zalign);
+ surflevel->nblk_x = ALIGN(surflevel->nblk_x, xalign);
+ surflevel->nblk_y = ALIGN(surflevel->nblk_y, yalign);
+ surflevel->nblk_z = ALIGN(surflevel->nblk_z, zalign);
- surf->level[level].offset = offset;
- surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe;
- surf->level[level].slice_size = surf->level[level].pitch_bytes * surf->level[level].nblk_y;
+ surflevel->offset = offset;
+ surflevel->pitch_bytes = surflevel->nblk_x * bpe * surf->nsamples;
+ surflevel->slice_size = surflevel->pitch_bytes * surflevel->nblk_y;
- surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+ surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
}
/* ===========================================================================
@@ -188,6 +192,7 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
if (version && version->version_minor >= 14) {
surf_man->hw_info.allow_2d = 1;
}
+ drmFreeVersion(version);
switch ((tiling_config & 0xe) >> 1) {
case 0:
@@ -203,7 +208,9 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.num_pipes = 8;
break;
default:
- return -EINVAL;
+ surf_man->hw_info.num_pipes = 8;
+ surf_man->hw_info.allow_2d = 0;
+ break;
}
switch ((tiling_config & 0x30) >> 4) {
@@ -214,7 +221,9 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.num_banks = 8;
break;
default:
- return -EINVAL;
+ surf_man->hw_info.num_banks = 8;
+ surf_man->hw_info.allow_2d = 0;
+ break;
}
switch ((tiling_config & 0xc0) >> 6) {
@@ -225,7 +234,9 @@ static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.group_bytes = 512;
break;
default:
- return -EINVAL;
+ surf_man->hw_info.group_bytes = 256;
+ surf_man->hw_info.allow_2d = 0;
+ break;
}
return 0;
}
@@ -254,7 +265,7 @@ static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
/* build mipmap tree */
for (i = start_level; i <= surf->last_level; i++) {
surf->level[i].mode = RADEON_SURF_MODE_LINEAR;
- surf_minify(surf, i, xalign, yalign, zalign, offset);
+ surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
/* level0 and first mipmap need to have alignment */
offset = surf->bo_size;
if ((i == 0)) {
@@ -282,7 +293,7 @@ static int r6_surface_init_linear_aligned(struct radeon_surface_manager *surf_ma
/* build mipmap tree */
for (i = start_level; i <= surf->last_level; i++) {
surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
- surf_minify(surf, i, xalign, yalign, zalign, offset);
+ surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
/* level0 and first mipmap need to have alignment */
offset = surf->bo_size;
if ((i == 0)) {
@@ -315,7 +326,7 @@ static int r6_surface_init_1d(struct radeon_surface_manager *surf_man,
/* build mipmap tree */
for (i = start_level; i <= surf->last_level; i++) {
surf->level[i].mode = RADEON_SURF_MODE_1D;
- surf_minify(surf, i, xalign, yalign, zalign, offset);
+ surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
/* level0 and first mipmap need to have alignment */
offset = surf->bo_size;
if ((i == 0)) {
@@ -346,14 +357,14 @@ static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
surf->bo_alignment =
MAX2(surf_man->hw_info.num_pipes *
surf_man->hw_info.num_banks *
- surf->bpe * 64,
+ surf->nsamples * surf->bpe * 64,
xalign * yalign * surf->nsamples * surf->bpe);
}
/* build mipmap tree */
for (i = start_level; i <= surf->last_level; i++) {
surf->level[i].mode = RADEON_SURF_MODE_2D;
- surf_minify(surf, i, xalign, yalign, zalign, offset);
+ surf_minify(surf, surf->level+i, surf->bpe, i, xalign, yalign, zalign, offset);
if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
return r6_surface_init_1d(surf_man, surf, offset, i);
}
@@ -372,11 +383,35 @@ static int r6_surface_init(struct radeon_surface_manager *surf_man,
unsigned mode;
int r;
+ /* MSAA surfaces support the 2D mode only. */
+ if (surf->nsamples > 1) {
+ surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+ surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+ }
+
/* tiling mode */
mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
+ if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+ /* zbuffer only support 1D or 2D tiled surface */
+ switch (mode) {
+ case RADEON_SURF_MODE_1D:
+ case RADEON_SURF_MODE_2D:
+ break;
+ default:
+ mode = RADEON_SURF_MODE_1D;
+ surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+ surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+ break;
+ }
+ }
+
/* force 1d on kernel that can't do 2d */
if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
+ if (surf->nsamples > 1) {
+ fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
+ return -EFAULT;
+ }
mode = RADEON_SURF_MODE_1D;
surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
surf->flags |= RADEON_SURF_SET(mode, MODE);
@@ -437,9 +472,10 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.allow_2d = 0;
version = drmGetVersion(surf_man->fd);
- if (version && version->version_minor >= 14) {
+ if (version && version->version_minor >= 16) {
surf_man->hw_info.allow_2d = 1;
}
+ drmFreeVersion(version);
switch (tiling_config & 0xf) {
case 0:
@@ -455,7 +491,9 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.num_pipes = 8;
break;
default:
- return -EINVAL;
+ surf_man->hw_info.num_pipes = 8;
+ surf_man->hw_info.allow_2d = 0;
+ break;
}
switch ((tiling_config & 0xf0) >> 4) {
@@ -469,7 +507,9 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.num_banks = 16;
break;
default:
- return -EINVAL;
+ surf_man->hw_info.num_banks = 8;
+ surf_man->hw_info.allow_2d = 0;
+ break;
}
switch ((tiling_config & 0xf00) >> 8) {
@@ -480,7 +520,9 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.group_bytes = 512;
break;
default:
- return -EINVAL;
+ surf_man->hw_info.group_bytes = 256;
+ surf_man->hw_info.allow_2d = 0;
+ break;
}
switch ((tiling_config & 0xf000) >> 12) {
@@ -494,12 +536,16 @@ static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
surf_man->hw_info.row_size = 4096;
break;
default:
- return -EINVAL;
+ surf_man->hw_info.row_size = 4096;
+ surf_man->hw_info.allow_2d = 0;
+ break;
}
return 0;
}
static void eg_surf_minify(struct radeon_surface *surf,
+ struct radeon_surface_level *surflevel,
+ unsigned bpe,
unsigned level,
unsigned slice_pt,
unsigned mtilew,
@@ -509,36 +555,38 @@ static void eg_surf_minify(struct radeon_surface *surf,
{
unsigned mtile_pr, mtile_ps;
- surf->level[level].npix_x = mip_minify(surf->npix_x, level);
- surf->level[level].npix_y = mip_minify(surf->npix_y, level);
- surf->level[level].npix_z = mip_minify(surf->npix_z, level);
- surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
- surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
- surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
- if (surf->level[level].mode == RADEON_SURF_MODE_2D) {
- if (surf->level[level].nblk_x < mtilew || surf->level[level].nblk_y < mtileh) {
- surf->level[level].mode = RADEON_SURF_MODE_1D;
+ surflevel->npix_x = mip_minify(surf->npix_x, level);
+ surflevel->npix_y = mip_minify(surf->npix_y, level);
+ surflevel->npix_z = mip_minify(surf->npix_z, level);
+ surflevel->nblk_x = (surflevel->npix_x + surf->blk_w - 1) / surf->blk_w;
+ surflevel->nblk_y = (surflevel->npix_y + surf->blk_h - 1) / surf->blk_h;
+ surflevel->nblk_z = (surflevel->npix_z + surf->blk_d - 1) / surf->blk_d;
+ if (surf->nsamples == 1 && surflevel->mode == RADEON_SURF_MODE_2D) {
+ if (surflevel->nblk_x < mtilew || surflevel->nblk_y < mtileh) {
+ surflevel->mode = RADEON_SURF_MODE_1D;
return;
}
}
- surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, mtilew);
- surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, mtileh);
- surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, 1);
+ surflevel->nblk_x = ALIGN(surflevel->nblk_x, mtilew);
+ surflevel->nblk_y = ALIGN(surflevel->nblk_y, mtileh);
+ surflevel->nblk_z = ALIGN(surflevel->nblk_z, 1);
/* macro tile per row */
- mtile_pr = surf->level[level].nblk_x / mtilew;
+ mtile_pr = surflevel->nblk_x / mtilew;
/* macro tile per slice */
- mtile_ps = (mtile_pr * surf->level[level].nblk_y) / mtileh;
+ mtile_ps = (mtile_pr * surflevel->nblk_y) / mtileh;
- surf->level[level].offset = offset;
- surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * slice_pt;
- surf->level[level].slice_size = mtile_ps * mtileb * slice_pt;
+ surflevel->offset = offset;
+ surflevel->pitch_bytes = surflevel->nblk_x * bpe * slice_pt;
+ surflevel->slice_size = mtile_ps * mtileb * slice_pt;
- surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+ surf->bo_size = offset + surflevel->slice_size * surflevel->nblk_z * surf->array_size;
}
static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
struct radeon_surface *surf,
+ struct radeon_surface_level *level,
+ unsigned bpe,
uint64_t offset, unsigned start_level)
{
uint32_t xalign, yalign, zalign, tilew;
@@ -546,43 +594,40 @@ static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
/* compute alignment */
tilew = 8;
- xalign = surf_man->hw_info.group_bytes / (tilew * surf->bpe * surf->nsamples);
- if (surf->flags & RADEON_SURF_SBUFFER) {
- surf->stencil_offset = 0;
- surf->stencil_tile_split = 0;
- xalign = surf_man->hw_info.group_bytes / (tilew * surf->nsamples);
- }
+ xalign = surf_man->hw_info.group_bytes / (tilew * bpe * surf->nsamples);
xalign = MAX2(tilew, xalign);
yalign = tilew;
zalign = 1;
if (surf->flags & RADEON_SURF_SCANOUT) {
- xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
+ xalign = MAX2((bpe == 1) ? 64 : 32, xalign);
}
+
if (!start_level) {
- surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+ unsigned alignment = MAX2(256, surf_man->hw_info.group_bytes);
+ surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
+
+ if (offset) {
+ offset = ALIGN(offset, alignment);
+ }
}
/* build mipmap tree */
for (i = start_level; i <= surf->last_level; i++) {
- surf->level[i].mode = RADEON_SURF_MODE_1D;
- surf_minify(surf, i, xalign, yalign, zalign, offset);
+ level[i].mode = RADEON_SURF_MODE_1D;
+ surf_minify(surf, level+i, bpe, i, xalign, yalign, zalign, offset);
/* level0 and first mipmap need to have alignment */
offset = surf->bo_size;
if ((i == 0)) {
offset = ALIGN(offset, surf->bo_alignment);
}
}
-
- if (surf->flags & RADEON_SURF_SBUFFER) {
- surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
- surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
- }
-
return 0;
}
static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
struct radeon_surface *surf,
+ struct radeon_surface_level *level,
+ unsigned bpe, unsigned tile_split,
uint64_t offset, unsigned start_level)
{
unsigned tilew, tileh, tileb;
@@ -590,15 +635,14 @@ static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
unsigned slice_pt;
unsigned i;
- surf->stencil_offset = 0;
/* compute tile values */
tilew = 8;
tileh = 8;
- tileb = tilew * tileh * surf->bpe * surf->nsamples;
+ tileb = tilew * tileh * bpe * surf->nsamples;
/* slices per tile */
slice_pt = 1;
- if (tileb > surf->tile_split) {
- slice_pt = tileb / surf->tile_split;
+ if (tileb > tile_split) {
+ slice_pt = tileb / tile_split;
}
tileb = tileb / slice_pt;
@@ -609,15 +653,20 @@ static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
if (!start_level) {
- surf->bo_alignment = MAX2(256, mtileb);
+ unsigned alignment = MAX2(256, mtileb);
+ surf->bo_alignment = MAX2(surf->bo_alignment, alignment);
+
+ if (offset) {
+ offset = ALIGN(offset, alignment);
+ }
}
/* build mipmap tree */
for (i = start_level; i <= surf->last_level; i++) {
- surf->level[i].mode = RADEON_SURF_MODE_2D;
- eg_surf_minify(surf, i, slice_pt, mtilew, mtileh, mtileb, offset);
- if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
- return eg_surface_init_1d(surf_man, surf, offset, i);
+ level[i].mode = RADEON_SURF_MODE_2D;
+ eg_surf_minify(surf, level+i, bpe, i, slice_pt, mtilew, mtileh, mtileb, offset);
+ if (level[i].mode == RADEON_SURF_MODE_1D) {
+ return eg_surface_init_1d(surf_man, surf, level, bpe, offset, i);
}
/* level0 and first mipmap need to have alignment */
offset = surf->bo_size;
@@ -625,12 +674,6 @@ static int eg_surface_init_2d(struct radeon_surface_manager *surf_man,
offset = ALIGN(offset, surf->bo_alignment);
}
}
-
- if (surf->flags & RADEON_SURF_SBUFFER) {
- surf->stencil_offset = ALIGN(surf->bo_size, surf->bo_alignment);
- surf->bo_size = surf->stencil_offset + surf->bo_size / 4;
- }
-
return 0;
}
@@ -652,6 +695,10 @@ static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
/* force 1d on kernel that can't do 2d */
if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
+ if (surf->nsamples > 1) {
+ fprintf(stderr, "radeon: Cannot use 2D tiling for an MSAA surface (%i).\n", __LINE__);
+ return -EFAULT;
+ }
mode = RADEON_SURF_MODE_1D;
surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
surf->flags |= RADEON_SURF_SET(mode, MODE);
@@ -713,18 +760,78 @@ static int eg_surface_sanity(struct radeon_surface_manager *surf_man,
return 0;
}
+static int eg_surface_init_1d_miptrees(struct radeon_surface_manager *surf_man,
+ struct radeon_surface *surf)
+{
+ unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
+ int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
+ /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
+ struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
+ struct radeon_surface_level *stencil_level =
+ (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
+
+ r = eg_surface_init_1d(surf_man, surf, surf->level, surf->bpe, 0, 0);
+ if (r)
+ return r;
+
+ if (is_depth_stencil) {
+ r = eg_surface_init_1d(surf_man, surf, stencil_level, 1,
+ surf->bo_size, 0);
+ surf->stencil_offset = stencil_level[0].offset;
+ }
+ return r;
+}
+
+static int eg_surface_init_2d_miptrees(struct radeon_surface_manager *surf_man,
+ struct radeon_surface *surf)
+{
+ unsigned zs_flags = RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER;
+ int r, is_depth_stencil = (surf->flags & zs_flags) == zs_flags;
+ /* Old libdrm headers didn't have stencil_level in it. This prevents crashes. */
+ struct radeon_surface_level tmp[RADEON_SURF_MAX_LEVEL];
+ struct radeon_surface_level *stencil_level =
+ (surf->flags & RADEON_SURF_HAS_SBUFFER_MIPTREE) ? surf->stencil_level : tmp;
+
+ r = eg_surface_init_2d(surf_man, surf, surf->level, surf->bpe,
+ surf->tile_split, 0, 0);
+ if (r)
+ return r;
+
+ if (is_depth_stencil) {
+ r = eg_surface_init_2d(surf_man, surf, stencil_level, 1,
+ surf->stencil_tile_split, surf->bo_size, 0);
+ surf->stencil_offset = stencil_level[0].offset;
+ }
+ return r;
+}
+
static int eg_surface_init(struct radeon_surface_manager *surf_man,
struct radeon_surface *surf)
{
unsigned mode;
int r;
+ /* MSAA surfaces support the 2D mode only. */
+ if (surf->nsamples > 1) {
+ surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+ surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+ }
+
/* tiling mode */
mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- /* for some reason eg need to have room for stencil right after depth */
- if (surf->flags & RADEON_SURF_ZBUFFER) {
- surf->flags |= RADEON_SURF_SBUFFER;
+ if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+ /* zbuffer only support 1D or 2D tiled surface */
+ switch (mode) {
+ case RADEON_SURF_MODE_1D:
+ case RADEON_SURF_MODE_2D:
+ break;
+ default:
+ mode = RADEON_SURF_MODE_1D;
+ surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+ surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+ break;
+ }
}
r = eg_surface_sanity(surf_man, surf, mode);
@@ -732,6 +839,9 @@ static int eg_surface_init(struct radeon_surface_manager *surf_man,
return r;
}
+ surf->stencil_offset = 0;
+ surf->bo_alignment = 0;
+
/* check tiling mode */
switch (mode) {
case RADEON_SURF_MODE_LINEAR:
@@ -741,10 +851,10 @@ static int eg_surface_init(struct radeon_surface_manager *surf_man,
r = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
break;
case RADEON_SURF_MODE_1D:
- r = eg_surface_init_1d(surf_man, surf, 0, 0);
+ r = eg_surface_init_1d_miptrees(surf_man, surf);
break;
case RADEON_SURF_MODE_2D:
- r = eg_surface_init_2d(surf_man, surf, 0, 0);
+ r = eg_surface_init_2d_miptrees(surf_man, surf);
break;
default:
return -EINVAL;
@@ -779,11 +889,6 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
/* tiling mode */
mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
- /* for some reason eg need to have room for stencil right after depth */
- if (surf->flags & RADEON_SURF_ZBUFFER) {
- surf->flags |= RADEON_SURF_SBUFFER;
- }
-
/* set some default value to avoid sanity check choking on them */
surf->tile_split = 1024;
surf->bankw = 1;
@@ -809,12 +914,39 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
return 0;
}
- /* set tile split to row size, optimize latter for multi-sample surface
- * tile split >= 256 for render buffer surface. Also depth surface want
- * smaller value for optimal performances.
- */
- surf->tile_split = surf_man->hw_info.row_size;
- surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
+ /* Tweak TILE_SPLIT for performance here. */
+ if (surf->nsamples > 1) {
+ if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+ switch (surf->nsamples) {
+ case 2:
+ surf->tile_split = 128;
+ break;
+ case 4:
+ surf->tile_split = 128;
+ break;
+ case 8:
+ surf->tile_split = 256;
+ break;
+ case 16: /* cayman only */
+ surf->tile_split = 512;
+ break;
+ default:
+ fprintf(stderr, "radeon: Wrong number of samples %i (%i)\n",
+ surf->nsamples, __LINE__);
+ return -EINVAL;
+ }
+ surf->stencil_tile_split = 64;
+ } else {
+ /* tile split must be >= 256 for colorbuffer surfaces */
+ surf->tile_split = MAX2(surf->nsamples * surf->bpe * 64, 256);
+ if (surf->tile_split > 4096)
+ surf->tile_split = 4096;
+ }
+ } else {
+ /* set tile split to row size */
+ surf->tile_split = surf_man->hw_info.row_size;
+ surf->stencil_tile_split = surf_man->hw_info.row_size / 2;
+ }
/* bankw or bankh greater than 1 increase alignment requirement, not
* sure if it's worth using smaller bankw & bankh to stick with 2D
@@ -824,7 +956,7 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
* fmask buffer has different optimal value figure them out once we
* use it.
*/
- if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+ if (surf->flags & RADEON_SURF_SBUFFER) {
/* assume 1 bytes for stencil, we optimize for stencil as stencil
* and depth shares surface values
*/
@@ -865,6 +997,136 @@ static int eg_surface_best(struct radeon_surface_manager *surf_man,
/* ===========================================================================
+ * Southern Islands family
+ */
+
+static void si_surf_minify_linear_aligned(struct radeon_surface *surf,
+ unsigned level,
+ uint32_t xalign, uint32_t yalign, uint32_t zalign, uint32_t slice_align,
+ unsigned offset)
+{
+ surf->level[level].npix_x = mip_minify(surf->npix_x, level);
+ surf->level[level].npix_y = mip_minify(surf->npix_y, level);
+ surf->level[level].npix_z = mip_minify(surf->npix_z, level);
+
+ if (level == 0 && surf->last_level > 0) {
+ surf->level[level].nblk_x = (next_power_of_two(surf->level[level].npix_x) + surf->blk_w - 1) / surf->blk_w;
+ surf->level[level].nblk_y = (next_power_of_two(surf->level[level].npix_y) + surf->blk_h - 1) / surf->blk_h;
+ surf->level[level].nblk_z = (next_power_of_two(surf->level[level].npix_z) + surf->blk_d - 1) / surf->blk_d;
+ } else {
+ surf->level[level].nblk_x = (surf->level[level].npix_x + surf->blk_w - 1) / surf->blk_w;
+ surf->level[level].nblk_y = (surf->level[level].npix_y + surf->blk_h - 1) / surf->blk_h;
+ surf->level[level].nblk_z = (surf->level[level].npix_z + surf->blk_d - 1) / surf->blk_d;
+ }
+
+ /* XXX: Texture sampling uses unexpectedly large pitches in some cases,
+ * these are just guesses for the rules behind those
+ */
+ if (level == 0 && surf->last_level == 0)
+ /* Non-mipmap pitch padded to slice alignment */
+ xalign = MAX2(xalign, slice_align / surf->bpe);
+ else
+ /* Small rows evenly distributed across slice */
+ xalign = MAX2(xalign, slice_align / surf->bpe / surf->level[level].npix_y);
+
+ surf->level[level].nblk_x = ALIGN(surf->level[level].nblk_x, xalign);
+ surf->level[level].nblk_y = ALIGN(surf->level[level].nblk_y, yalign);
+ surf->level[level].nblk_z = ALIGN(surf->level[level].nblk_z, zalign);
+
+ surf->level[level].offset = offset;
+ surf->level[level].pitch_bytes = surf->level[level].nblk_x * surf->bpe * surf->nsamples;
+ surf->level[level].slice_size = ALIGN(surf->level[level].pitch_bytes * surf->level[level].nblk_y, slice_align);
+
+ surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+}
+
+static int si_surface_init_linear_aligned(struct radeon_surface_manager *surf_man,
+ struct radeon_surface *surf,
+ uint64_t offset, unsigned start_level)
+{
+ uint32_t xalign, yalign, zalign, slice_align;
+ unsigned i;
+
+ /* compute alignment */
+ if (!start_level) {
+ surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+ }
+ xalign = MAX2(8, 64 / surf->bpe);
+ yalign = 1;
+ zalign = 1;
+ slice_align = MAX2(64 * surf->bpe, surf_man->hw_info.group_bytes);
+
+ /* build mipmap tree */
+ for (i = start_level; i <= surf->last_level; i++) {
+ surf->level[i].mode = RADEON_SURF_MODE_LINEAR_ALIGNED;
+ si_surf_minify_linear_aligned(surf, i, xalign, yalign, zalign, slice_align, offset);
+ /* level0 and first mipmap need to have alignment */
+ offset = surf->bo_size;
+ if ((i == 0)) {
+ offset = ALIGN(offset, surf->bo_alignment);
+ }
+ }
+ return 0;
+}
+
+static int si_surface_init(struct radeon_surface_manager *surf_man,
+ struct radeon_surface *surf)
+{
+ unsigned mode;
+ int r;
+
+ /* MSAA surfaces support the 2D mode only. */
+ if (surf->nsamples > 1) {
+ surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+ surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_2D, MODE);
+ }
+
+ /* tiling mode */
+ mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
+
+ if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+ /* zbuffer only support 1D or 2D tiled surface */
+ switch (mode) {
+ case RADEON_SURF_MODE_1D:
+ case RADEON_SURF_MODE_2D:
+ break;
+ default:
+ mode = RADEON_SURF_MODE_1D;
+ surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+ surf->flags |= RADEON_SURF_SET(RADEON_SURF_MODE_1D, MODE);
+ break;
+ }
+ }
+
+ r = eg_surface_sanity(surf_man, surf, mode);
+ if (r) {
+ return r;
+ }
+
+ surf->stencil_offset = 0;
+ surf->bo_alignment = 0;
+
+ /* check tiling mode */
+ switch (mode) {
+ case RADEON_SURF_MODE_LINEAR:
+ r = r6_surface_init_linear(surf_man, surf, 0, 0);
+ break;
+ case RADEON_SURF_MODE_LINEAR_ALIGNED:
+ r = si_surface_init_linear_aligned(surf_man, surf, 0, 0);
+ break;
+ case RADEON_SURF_MODE_1D:
+ r = eg_surface_init_1d_miptrees(surf_man, surf);
+ break;
+ case RADEON_SURF_MODE_2D:
+ r = eg_surface_init_2d_miptrees(surf_man, surf);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return r;
+}
+
+/* ===========================================================================
* public API
*/
struct radeon_surface_manager *radeon_surface_manager_new(int fd)
@@ -893,7 +1155,11 @@ struct radeon_surface_manager *radeon_surface_manager_new(int fd)
if (eg_init_hw_info(surf_man)) {
goto out_err;
}
- surf_man->surface_init = &eg_surface_init;
+ if (surf_man->family <= CHIP_ARUBA) {
+ surf_man->surface_init = &eg_surface_init;
+ } else {
+ surf_man->surface_init = &si_surface_init;
+ }
surf_man->surface_best = &eg_surface_best;
}
diff --git a/radeon/radeon_surface.h b/radeon/radeon_surface.h
index bfee8ab..ed4b994 100644
--- a/radeon/radeon_surface.h
+++ b/radeon/radeon_surface.h
@@ -54,6 +54,7 @@
#define RADEON_SURF_SCANOUT (1 << 16)
#define RADEON_SURF_ZBUFFER (1 << 17)
#define RADEON_SURF_SBUFFER (1 << 18)
+#define RADEON_SURF_HAS_SBUFFER_MIPTREE (1 << 19)
#define RADEON_SURF_GET(v, field) (((v) >> RADEON_SURF_ ## field ## _SHIFT) & RADEON_SURF_ ## field ## _MASK)
#define RADEON_SURF_SET(v, field) (((v) & RADEON_SURF_ ## field ## _MASK) << RADEON_SURF_ ## field ## _SHIFT)
@@ -102,6 +103,7 @@ struct radeon_surface {
uint32_t stencil_tile_split;
uint64_t stencil_offset;
struct radeon_surface_level level[RADEON_SURF_MAX_LEVEL];
+ struct radeon_surface_level stencil_level[RADEON_SURF_MAX_LEVEL];
};
struct radeon_surface_manager *radeon_surface_manager_new(int fd);
diff --git a/tests/modetest/Makefile.am b/tests/modetest/Makefile.am
index 2191242..065ae13 100644
diff --git a/tests/modetest/buffers.c b/tests/modetest/buffers.c
new file mode 100644
index 0000000..5086381
diff --git a/tests/modetest/buffers.h b/tests/modetest/buffers.h
new file mode 100644
index 0000000..2b15ce5
diff --git a/tests/modetest/modetest.c b/tests/modetest/modetest.c
index 1e4ec91..c91bb9d 100644
diff --git a/tests/vbltest/vbltest.c b/tests/vbltest/vbltest.c
index 903ca0f..4fccd59 100644
diff --git a/xf86drm.c b/xf86drm.c
index 6ea068f..2a74c80 100644
--- a/xf86drm.c
+++ b/xf86drm.c
@@ -2542,3 +2542,34 @@ char *drmGetDeviceNameFromFd(int fd)
return strdup(name);
}
+
+int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd)
+{
+ struct drm_prime_handle args;
+ int ret;
+
+ args.handle = handle;
+ args.flags = flags;
+ ret = drmIoctl(fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &args);
+ if (ret)
+ return ret;
+
+ *prime_fd = args.fd;
+ return 0;
+}
+
+int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle)
+{
+ struct drm_prime_handle args;
+ int ret;
+
+ args.fd = prime_fd;
+ args.flags = 0;
+ ret = drmIoctl(fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &args);
+ if (ret)
+ return ret;
+
+ *handle = args.handle;
+ return 0;
+}
+
diff --git a/xf86drm.h b/xf86drm.h
index 76eb94e..5ecb284 100644
--- a/xf86drm.h
+++ b/xf86drm.h
@@ -727,6 +727,9 @@ extern int drmHandleEvent(int fd, drmEventContextPtr evctx);
extern char *drmGetDeviceNameFromFd(int fd);
+extern int drmPrimeHandleToFD(int fd, uint32_t handle, uint32_t flags, int *prime_fd);
+extern int drmPrimeFDToHandle(int fd, int prime_fd, uint32_t *handle);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
diff --git a/xf86drmMode.c b/xf86drmMode.c
index c809c44..f603ceb 100644
--- a/xf86drmMode.c
+++ b/xf86drmMode.c
@@ -351,8 +351,11 @@ drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
r->x = crtc.x;
r->y = crtc.y;
r->mode_valid = crtc.mode_valid;
- if (r->mode_valid)
+ if (r->mode_valid) {
memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
+ r->width = crtc.mode.hdisplay;
+ r->height = crtc.mode.vdisplay;
+ }
r->buffer_id = crtc.fb_id;
r->gamma_size = crtc.gamma_size;
return r;
@@ -575,7 +578,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
if (prop.count_values)
prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
- if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
+ if (prop.count_enum_blobs && (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
@@ -597,7 +600,7 @@ drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
r->flags = prop.flags;
if (prop.count_values)
r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
- if (prop.flags & DRM_MODE_PROP_ENUM) {
+ if (prop.flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
r->count_enums = prop.count_enum_blobs;
r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
} else if (prop.flags & DRM_MODE_PROP_BLOB) {
@@ -974,3 +977,86 @@ void drmModeFreePlaneResources(drmModePlaneResPtr ptr)
drmFree(ptr->planes);
drmFree(ptr);
}
+
+drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,
+ uint32_t object_id,
+ uint32_t object_type)
+{
+ struct drm_mode_obj_get_properties properties;
+ drmModeObjectPropertiesPtr ret = NULL;
+ uint32_t count;
+
+retry:
+ memset(&properties, 0, sizeof(struct drm_mode_obj_get_properties));
+ properties.obj_id = object_id;
+ properties.obj_type = object_type;
+
+ if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))
+ return 0;
+
+ count = properties.count_props;
+
+ if (count) {
+ properties.props_ptr = VOID2U64(drmMalloc(count *
+ sizeof(uint32_t)));
+ if (!properties.props_ptr)
+ goto err_allocs;
+ properties.prop_values_ptr = VOID2U64(drmMalloc(count *
+ sizeof(uint64_t)));
+ if (!properties.prop_values_ptr)
+ goto err_allocs;
+ }
+
+ if (drmIoctl(fd, DRM_IOCTL_MODE_OBJ_GETPROPERTIES, &properties))
+ goto err_allocs;
+
+ if (count < properties.count_props) {
+ drmFree(U642VOID(properties.props_ptr));
+ drmFree(U642VOID(properties.prop_values_ptr));
+ goto retry;
+ }
+ count = properties.count_props;
+
+ ret = drmMalloc(sizeof(*ret));
+ if (!ret)
+ goto err_allocs;
+
+ ret->count_props = count;
+ ret->props = drmAllocCpy(U642VOID(properties.props_ptr),
+ count, sizeof(uint32_t));
+ ret->prop_values = drmAllocCpy(U642VOID(properties.prop_values_ptr),
+ count, sizeof(uint64_t));
+ if (ret->count_props && (!ret->props || !ret->prop_values)) {
+ drmFree(ret->props);
+ drmFree(ret->prop_values);
+ drmFree(ret);
+ ret = NULL;
+ }
+
+err_allocs:
+ drmFree(U642VOID(properties.props_ptr));
+ drmFree(U642VOID(properties.prop_values_ptr));
+ return ret;
+}
+
+void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr)
+{
+ if (!ptr)
+ return;
+ drmFree(ptr->props);
+ drmFree(ptr->prop_values);
+ drmFree(ptr);
+}
+
+int drmModeObjectSetProperty(int fd, uint32_t object_id, uint32_t object_type,
+ uint32_t property_id, uint64_t value)
+{
+ struct drm_mode_obj_set_property prop;
+
+ prop.value = value;
+ prop.prop_id = property_id;
+ prop.obj_id = object_id;
+ prop.obj_type = object_type;
+
+ return DRM_IOCTL(fd, DRM_IOCTL_MODE_OBJ_SETPROPERTY, &prop);
+}
diff --git a/xf86drmMode.h b/xf86drmMode.h
index 991e3f9..8e40034 100644
--- a/xf86drmMode.h
+++ b/xf86drmMode.h
@@ -281,6 +281,12 @@ typedef struct _drmModeConnector {
uint32_t *encoders; /**< List of encoder ids */
} drmModeConnector, *drmModeConnectorPtr;
+typedef struct _drmModeObjectProperties {
+ uint32_t count_props;
+ uint32_t *props;
+ uint64_t *prop_values;
+} drmModeObjectProperties, *drmModeObjectPropertiesPtr;
+
typedef struct _drmModePlane {
uint32_t count_formats;
uint32_t *formats;
@@ -428,6 +434,14 @@ extern int drmModeSetPlane(int fd, uint32_t plane_id, uint32_t crtc_id,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
+extern drmModeObjectPropertiesPtr drmModeObjectGetProperties(int fd,
+ uint32_t object_id,
+ uint32_t object_type);
+extern void drmModeFreeObjectProperties(drmModeObjectPropertiesPtr ptr);
+extern int drmModeObjectSetProperty(int fd, uint32_t object_id,
+ uint32_t object_type, uint32_t property_id,
+ uint64_t value);
+
#if defined(__cplusplus) || defined(c_plusplus)
}
#endif
Attachment:
signature.asc
Description: Digital signature