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