upload tizen2.0 source 2.0alpha master 2.0_alpha submit/master/20120920.151131
authorBoram Park <boram1288.park@samsung.com>
Tue, 21 Aug 2012 09:04:23 +0000 (18:04 +0900)
committerBoram Park <boram1288.park@samsung.com>
Tue, 21 Aug 2012 09:04:23 +0000 (18:04 +0900)
134 files changed:
Makefile.am
autogen.sh [changed mode: 0755->0644]
build.sh [new file with mode: 0644]
configure.ac
debian/changelog
debian/libdrm-dev.install
debian/libdrm2.install
debian/rules [changed mode: 0755->0644]
exynos/Makefile.am [new file with mode: 0644]
exynos/exynos_drm.c [new file with mode: 0644]
exynos/exynos_drm.h [new file with mode: 0644]
exynos/exynos_drmif.h [new file with mode: 0644]
exynos/libdrm_exynos.pc.in [new file with mode: 0644]
include/drm/Makefile.am [changed mode: 0755->0644]
include/drm/drm.h
include/drm/drm_fourcc.h
include/drm/drm_mode.h [changed mode: 0755->0644]
include/drm/exynos_drm.h [deleted file]
include/drm/i915_drm.h
include/drm/radeon_drm.h
intel/.gitignore [new file with mode: 0644]
intel/Makefile.am
intel/intel_aub.h [new file with mode: 0644]
intel/intel_bufmgr.h
intel/intel_bufmgr_gem.c
intel/intel_chipset.h
intel/intel_decode.c [new file with mode: 0644]
intel/test_decode.c [new file with mode: 0644]
intel/tests/.gitignore [new file with mode: 0644]
intel/tests/gen4-3d.batch [new file with mode: 0644]
intel/tests/gen4-3d.batch-ref.txt [new file with mode: 0644]
intel/tests/gen4-3d.batch.sh [new file with mode: 0644]
intel/tests/gen5-3d.batch [new file with mode: 0644]
intel/tests/gen5-3d.batch-ref.txt [new file with mode: 0644]
intel/tests/gen5-3d.batch.sh [new file with mode: 0644]
intel/tests/gen6-3d.batch [new file with mode: 0644]
intel/tests/gen6-3d.batch-ref.txt [new file with mode: 0644]
intel/tests/gen6-3d.batch.sh [new file with mode: 0644]
intel/tests/gen7-2d-copy.batch [new file with mode: 0644]
intel/tests/gen7-2d-copy.batch-ref.txt [new file with mode: 0644]
intel/tests/gen7-2d-copy.batch.sh [new file with mode: 0644]
intel/tests/gen7-3d.batch [new file with mode: 0644]
intel/tests/gen7-3d.batch-ref.txt [new file with mode: 0644]
intel/tests/gen7-3d.batch.sh [new file with mode: 0644]
intel/tests/gm45-3d.batch [new file with mode: 0644]
intel/tests/gm45-3d.batch-ref.txt [new file with mode: 0644]
intel/tests/gm45-3d.batch.sh [new file with mode: 0644]
intel/tests/test-batch.sh [new file with mode: 0644]
libdrm.pc.in
libdrm_lists.h
libkms/Makefile.am
libkms/dumb.c [changed mode: 0755->0644]
libkms/internal.h
libkms/linux.c
nouveau/Makefile.am
nouveau/abi16.c [new file with mode: 0644]
nouveau/bufctx.c [new file with mode: 0644]
nouveau/libdrm_nouveau.pc.in
nouveau/nouveau.c [new file with mode: 0644]
nouveau/nouveau.h [new file with mode: 0644]
nouveau/nouveau_bo.c [deleted file]
nouveau/nouveau_bo.h [deleted file]
nouveau/nouveau_channel.c [deleted file]
nouveau/nouveau_channel.h [deleted file]
nouveau/nouveau_device.c [deleted file]
nouveau/nouveau_device.h [deleted file]
nouveau/nouveau_drmif.h [deleted file]
nouveau/nouveau_grobj.c [deleted file]
nouveau/nouveau_grobj.h [deleted file]
nouveau/nouveau_notifier.c [deleted file]
nouveau/nouveau_notifier.h [deleted file]
nouveau/nouveau_private.h [deleted file]
nouveau/nouveau_pushbuf.c [deleted file]
nouveau/nouveau_pushbuf.h [deleted file]
nouveau/nouveau_reloc.c [deleted file]
nouveau/nouveau_reloc.h [deleted file]
nouveau/nouveau_resource.c [deleted file]
nouveau/nouveau_resource.h [deleted file]
nouveau/nv04_pushbuf.h [deleted file]
nouveau/nvc0_pushbuf.h [deleted file]
nouveau/private.h [new file with mode: 0644]
nouveau/pushbuf.c [new file with mode: 0644]
omap/Makefile.am [new file with mode: 0644]
omap/libdrm_omap.pc.in [new file with mode: 0644]
omap/omap_drm.c [new file with mode: 0644]
omap/omap_drm.h [new file with mode: 0644]
omap/omap_drmif.h [new file with mode: 0644]
packaging/libdrm.spec
radeon/Makefile.am
radeon/r600_pci_ids.h [new file with mode: 0644]
radeon/radeon_cs_space.c
radeon/radeon_surface.c [new file with mode: 0644]
radeon/radeon_surface.h [new file with mode: 0644]
slp/drm_slp_bufmgr.c [changed mode: 0755->0644]
slp/drm_slp_bufmgr.h [changed mode: 0755->0644]
slp/list.h [new file with mode: 0644]
tests/Makefile.am
tests/g2dtest/Makefile.am [moved from tests/planetest/Makefile.am with 61% similarity]
tests/g2dtest/g2d.h [new file with mode: 0644]
tests/g2dtest/g2d_reg.h [new file with mode: 0644]
tests/g2dtest/g2dtest.c [new file with mode: 0644]
tests/gem_flink.c
tests/gemtest/Makefile.am
tests/gemtest/gemtest.c
tests/gemtest/ump.h [new file with mode: 0644]
tests/gemtest/ump_platform.h [new file with mode: 0644]
tests/gemtest/ump_ref_drv.h [new file with mode: 0644]
tests/ipptest/Makefile.am [new file with mode: 0644]
tests/ipptest/fimc.c [new file with mode: 0644]
tests/ipptest/fimc.h [new file with mode: 0644]
tests/ipptest/fimctest.c [new file with mode: 0644]
tests/ipptest/fimctest.h [new file with mode: 0644]
tests/ipptest/gem.c [new file with mode: 0644]
tests/ipptest/gem.h [new file with mode: 0644]
tests/ipptest/util.c [new file with mode: 0644]
tests/ipptest/util.h [new file with mode: 0644]
tests/modetest/Makefile.am
tests/modetest/modetest.c [changed mode: 0755->0644]
tests/planetest/planetest.c [deleted file]
tests/proptest/Makefile.am [new file with mode: 0644]
tests/proptest/proptest.c [new file with mode: 0644]
tests/rottest/Makefile.am [new file with mode: 0644]
tests/rottest/gem.c [new file with mode: 0644]
tests/rottest/gem.h [new file with mode: 0644]
tests/rottest/rotator.c [new file with mode: 0644]
tests/rottest/rotator.h [new file with mode: 0644]
tests/rottest/rottest.c [new file with mode: 0644]
tests/rottest/rottest.h [new file with mode: 0644]
tests/rottest/util.c [new file with mode: 0644]
tests/rottest/util.h [new file with mode: 0644]
tests/ttmtest/reconf [changed mode: 0755->0644]
tests/vbltest/vbltest.c
xf86drmMode.c
xf86drmMode.h

index 3846d3a..6e74607 100644 (file)
@@ -41,11 +41,19 @@ if HAVE_RADEON
 RADEON_SUBDIR = radeon
 endif
 
+if HAVE_OMAP
+OMAP_SUBDIR = omap
+endif
+
+if HAVE_EXYNOS
+EXYNOS_SUBDIR = exynos
+endif
+
 if HAVE_SLP
 SLP_SUBDIR = slp
 endif
 
-SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(SLP_SUBDIR) tests include
+SUBDIRS = . $(LIBKMS_SUBDIR) $(INTEL_SUBDIR) $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR) $(OMAP_SUBDIR) $(EXYNOS_SUBDIR) $(SLP_SUBDIR) tests include
 
 libdrm_la_LTLIBRARIES = libdrm.la
 libdrm_ladir = $(libdir)
old mode 100755 (executable)
new mode 100644 (file)
diff --git a/build.sh b/build.sh
new file mode 100644 (file)
index 0000000..c31e652
--- /dev/null
+++ b/build.sh
@@ -0,0 +1,42 @@
+#!/bin/sh
+
+USER=`whoami`
+PREFIX=/usr/local/build
+KERNEL_DIR=/home/pub/git/party/linux-mobile
+CROSS_COMPILER="/opt/toolchains/arm-linux-link/bin/arm-none-linux-gnueabi-"
+
+if [ "$USER" = "dofmind" ]; then
+       PREFIX=/usr/local/build
+       KERNEL_DIR=/home/pub/git/gerrit/linux-2.6
+       CROSS_COMPILER="/opt/toolchains/arm-linux-link/bin/arm-none-linux-gnueabi-"
+fi
+if [ "$USER" = "daeinki" ]; then
+       PREFIX=/home/daeinki/project/share
+       KERNEL_DIR=/home/daeinki/project/s5pc210/linux-mobile
+       CROSS_COMPILER="/usr/local/arm/arm-2009q3-93/bin/arm-none-linux-gnueabi-"
+fi
+
+HOST="`echo $CROSS_COMPILER | sed 's/.*bin\///' | sed 's/-$//'`"
+
+make distclean
+./autogen.sh
+./configure --host=$HOST --prefix=$PREFIX --disable-intel --disable-radeon --enable-exynos-experimental-api --with-kernel-source=$KERNEL_DIR
+
+sudo rm -rf $PREFIX
+sudo mkdir -p $PREFIX
+sudo chown $USER.$USER $PREFIX
+
+make
+make install
+
+mkdir $PREFIX/bin
+cp -a ./tests/gemtest/.libs/gemtest $PREFIX/bin
+cp -a ./tests/kmstest/.libs/kmstest $PREFIX/bin
+cp -a ./tests/modeprint/.libs/modeprint $PREFIX/bin
+cp -a ./tests/modetest/.libs/modetest $PREFIX/bin
+cp -a ./tests/proptest/.libs/proptest $PREFIX/bin
+cp -a ./tests/ipptest/.libs/ipptest $PREFIX/bin
+cp -a ./tests/g2dtest/.libs/g2dtest $PREFIX/bin
+cp -a ./tests/rottest/.libs/rottest $PREFIX/bin
+
+tar zcvf libdrm.tar.gz $PREFIX
index 527d1ad..68d1cdd 100644 (file)
@@ -20,7 +20,7 @@
 
 AC_PREREQ([2.63])
 AC_INIT([libdrm],
-        [2.4.29],
+        [2.4.35],
         [https://bugs.freedesktop.org/enter_bug.cgi?product=DRI],
         [libdrm])
 
@@ -51,10 +51,6 @@ PKG_CHECK_MODULES(PTHREADSTUBS, pthread-stubs)
 AC_SUBST(PTHREADSTUBS_CFLAGS)
 AC_SUBST(PTHREADSTUBS_LIBS)
 
-PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
-AC_SUBST(PCIACCESS_CFLAGS)
-AC_SUBST(PCIACCESS_LIBS)
-
 pkgconfigdir=${libdir}/pkgconfig
 AC_SUBST(pkgconfigdir)
 AC_ARG_ENABLE([udev],
@@ -77,15 +73,25 @@ AC_ARG_ENABLE(radeon,
              [Enable support for radeon's KMS API (default: auto)]),
              [RADEON=$enableval], [RADEON=auto])
 
+AC_ARG_ENABLE(nouveau,
+             AS_HELP_STRING([--disable-nouveau],
+             [Enable support for nouveau's KMS API (default: auto)]),
+             [NOUVEAU=$enableval], [NOUVEAU=auto])
+
 AC_ARG_ENABLE(vmwgfx-experimental-api,
              AS_HELP_STRING([--enable-vmwgfx-experimental-api],
              [Install vmwgfx's experimental kernel API header (default: disabled)]),
              [VMWGFX=$enableval], [VMWGFX=no])
 
-AC_ARG_ENABLE(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(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])
 
 AC_ARG_ENABLE(slp,
              AS_HELP_STRING([--disable-slp],
@@ -126,6 +132,8 @@ AC_CHECK_FUNCS([clock_gettime], [CLOCK_LIB=],
                              [AC_MSG_ERROR([Couldn't find clock_gettime])])])
 AC_SUBST([CLOCK_LIB])
 
+AC_CHECK_FUNCS([open_memstream], [HAVE_OPEN_MEMSTREAM=yes])
+
 dnl Use lots of warning flags with with gcc and compatible compilers
 
 dnl Note: if you change the following variable, the cache is automatically
@@ -196,6 +204,16 @@ if test "x$NOUVEAU" = xyes; then
        AC_DEFINE(HAVE_NOUVEAU, 1, [Have nouveau (nvidia) support])
 fi
 
+AM_CONDITIONAL(HAVE_OMAP, [test "x$OMAP" = xyes])
+if test "x$OMAP" = xyes; then
+       AC_DEFINE(HAVE_OMAP, 1, [Have OMAP support])
+fi
+
+AM_CONDITIONAL(HAVE_EXYNOS, [test "x$EXYNOS" = xyes])
+if test "x$EXYNOS" = xyes; then
+       AC_DEFINE(HAVE_EXYNOS, 1, [Have EXYNOS support])
+fi
+
 PKG_CHECK_MODULES(CAIRO, cairo, [HAVE_CAIRO=yes], [HAVE_CAIRO=no])
 if test "x$HAVE_CAIRO" = xyes; then
        AC_DEFINE(HAVE_CAIRO, 1, [Have cairo support])
@@ -209,7 +227,7 @@ if test "x$HAVE_LIBUDEV" = xyes; then
 fi
 AM_CONDITIONAL(HAVE_LIBUDEV, [test "x$HAVE_LIBUDEV" = xyes])
 
-if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$SLP" != "xno"; then
+if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$NOUVEAU" != "xno" -o "x$SLP" != "xno"; then
     # Check for atomic intrinsics
     AC_CACHE_CHECK([for native atomic primitives], drm_cv_atomic_primitives,
     [
@@ -257,14 +275,27 @@ if test "x$INTEL" != "xno" -o "x$RADEON" != "xno" -o "x$SLP" != "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
-                   INTEL=yes
+                   case $host_cpu in
+                           i?86|x86_64) INTEL=yes ;;
+                           *) INTEL=no ;;
+                   esac
            fi
            if test "x$RADEON" != "xno"; then
                    RADEON=yes
            fi
+           if test "x$NOUVEAU" != "xno"; then
+                   NOUVEAU=yes
+           fi
     fi
 fi
 
@@ -272,9 +303,21 @@ if test "x$SLP" != "xno"; then
        AC_DEFINE(HAVE_SLP, 1, [Have slp])
 fi
 
+if test "x$INTEL" != "xno"; then
+       PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10])
+fi
+AC_SUBST(PCIACCESS_CFLAGS)
+AC_SUBST(PCIACCESS_LIBS)
+
+PKG_CHECK_MODULES(VALGRIND, [valgrind], [have_valgrind=yes], [have_valgrind=no])
+if test "x$have_valgrind" = "xyes"; then
+       AC_DEFINE([HAVE_VALGRIND], 1, [Use valgrind intrinsics to suppress false warnings])
+fi
+
 AM_CONDITIONAL(HAVE_SLP, [test "x$SLP" != "xno"])
 AM_CONDITIONAL(HAVE_INTEL, [test "x$INTEL" != "xno"])
 AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" != "xno"])
+AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" != "xno"])
 if test "x$RADEON" = xyes; then
        AC_DEFINE(HAVE_RADEON, 1, [Have radeon support])
 fi
@@ -298,14 +341,21 @@ AC_CONFIG_FILES([
        radeon/libdrm_radeon.pc
        nouveau/Makefile
        nouveau/libdrm_nouveau.pc
+       omap/Makefile
+       omap/libdrm_omap.pc
+       exynos/Makefile
+       exynos/libdrm_exynos.pc
        tests/Makefile
        tests/modeprint/Makefile
        tests/modetest/Makefile
        tests/kmstest/Makefile
+       tests/proptest/Makefile
        tests/radeon/Makefile
        tests/vbltest/Makefile
        tests/gemtest/Makefile
-       tests/planetest/Makefile
+       tests/g2dtest/Makefile
+       tests/ipptest/Makefile
+       tests/rottest/Makefile
        include/Makefile
        include/drm/Makefile
        libdrm.pc])
@@ -319,6 +369,8 @@ echo "  Intel API      $INTEL"
 echo "  vmwgfx API     $VMWGFX"
 echo "  Radeon API     $RADEON"
 echo "  Nouveau API    $NOUVEAU"
+echo "  OMAP API       $OMAP"
+echo "  EXYNOS API     $EXYNOS"
 echo "  SLP API        $SLP"
 echo "  SLP bufmgr_dir $bufmgr_dir"
 echo ""
index 4740b56..58e7c5f 100644 (file)
@@ -1,3 +1,91 @@
+libdrm (2.4.35-1slp2) unstable; urgency=low
+
+  * upgrade to 2.4.35
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.35-1slp2
+
+ -- Boram Park <boram1288.park@samsung.com>  Mon, 11 Jun 2012 18:58:07 +0900
+
+libdrm (2.4.33-5slp2) unstable; urgency=low
+
+  * update changelog
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.33-5slp2
+
+ -- Boram Park <boram1288.park@samsung.com>  Tue, 29 May 2012 20:33:15 +0900
+
+libdrm (2.4.33-4slp2) unstable; urgency=low
+
+  * update for cacheflush
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.33-4slp2
+
+ -- Boram Park <boram1288.park@samsung.com>  Mon, 30 Apr 2012 16:46:47 +0900
+
+libdrm (2.4.33-3slp2) unstable; urgency=low
+
+  * fix : wrong condition
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.33-3slp2
+
+ -- Boram Park <boram1288.park@samsung.com>  Thu, 26 Apr 2012 15:10:55 +0900
+
+libdrm (2.4.33-2slp2) unstable; urgency=low
+
+  * update changelog
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.33-2slp2
+
+ -- Boram Park <boram1288.park@samsung.com>  Thu, 26 Apr 2012 11:06:32 +0900
+
+libdrm (2.4.33-1slp2) unstable; urgency=low
+
+  * version upgrade to 2.4.33
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.33-1slp2
+
+ -- Boram Park <boram1288.park@samsung.com>  Wed, 25 Apr 2012 11:38:37 +0900
+
+libdrm (2.4.27-18slp2) unstable; urgency=low
+
+  * update exynos_drm.h
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.27-18slp2
+
+ -- Boram Park <boram1288.park@samsung.com>  Thu, 29 Mar 2012 16:58:17 +0900
+
+libdrm (2.4.27-17slp2) unstable; urgency=low
+
+  * fix exynos_drm.h
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.27-17slp2
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Thu, 22 Mar 2012 20:33:18 +0900
+
+libdrm (2.4.27-16slp2) unstable; urgency=low
+
+  * update exynos_drm.h
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.27-16slp2
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Thu, 22 Mar 2012 20:00:05 +0900
+
+libdrm (2.4.27-15slp2) unstable; urgency=low
+
+  * update exynos_drm.h
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.27-15slp2
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Wed, 07 Mar 2012 13:16:38 +0900
+
+libdrm (2.4.27-14slp2) unstable; urgency=low
+
+  * update headers for g2d and virtual output
+  * Git: slp/pkgs/xorg/lib/libdrm
+  * Tag: libdrm_2.4.27-14slp2
+
+ -- SooChan Lim <sc1.lim@samsung.com>  Fri, 17 Feb 2012 15:19:47 +0900
+
 libdrm (2.4.27-13slp2) unstable; urgency=low
 
   * patch from kernel : add virtual display for wireless display
index 0c219ff..0fbec43 100644 (file)
@@ -1,6 +1,8 @@
 usr/include/*
+usr/include/exynos/*
 usr/lib/lib*.a
 usr/lib/lib*.la
 usr/lib/libdrm.so
+usr/lib/libdrm_exynos.so
 usr/lib/libdrm_slp.so
 usr/lib/pkgconfig/*
index 8383687..7cc185c 100644 (file)
@@ -1 +1,2 @@
 usr/lib/libdrm.so.* /usr/lib
+usr/lib/libdrm_exynos.so.* /usr/lib
old mode 100755 (executable)
new mode 100644 (file)
index eb4d728..bc5e503
@@ -38,7 +38,7 @@ confflags += --enable-udev
 #confflags += --disable-udev
 confflags += --enable-libkms
 LIBKMS=yes
-confflags += --disable-nouveau-experimental-api
+confflags += --disable-nouveau
 NOUVEAU = no
 confflags += --disable-radeon
 RADEON = no
@@ -86,7 +86,7 @@ obj-$(DEB_BUILD_GNU_TYPE)/config.status: configure
        test -d obj-$(DEB_BUILD_GNU_TYPE) || mkdir obj-$(DEB_BUILD_GNU_TYPE)
        cd obj-$(DEB_BUILD_GNU_TYPE) && \
        ../configure --prefix=/usr --mandir=\$${prefix}/share/man \
-               --infodir=\$${prefix}/share/info \
+               --infodir=\$${prefix}/share/info --enable-exynos-experimental-api \
                --enable-static=yes $(confflags) \
                CFLAGS="$(CFLAGS)" \
                LDFLAGS="$(CFLAGS)"
diff --git a/exynos/Makefile.am b/exynos/Makefile.am
new file mode 100644 (file)
index 0000000..e782d34
--- /dev/null
@@ -0,0 +1,22 @@
+AM_CFLAGS = \
+       $(WARN_CFLAGS) \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/exynos \
+       $(PTHREADSTUBS_CFLAGS) \
+       -I$(top_srcdir)/include/drm
+
+libdrm_exynos_la_LTLIBRARIES = libdrm_exynos.la
+libdrm_exynos_ladir = $(libdir)
+libdrm_exynos_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libdrm_exynos_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
+
+libdrm_exynos_la_SOURCES = exynos_drm.c
+
+libdrm_exynoscommonincludedir = ${includedir}/exynos
+libdrm_exynoscommoninclude_HEADERS = exynos_drm.h
+
+libdrm_exynosincludedir = ${includedir}/libdrm
+libdrm_exynosinclude_HEADERS = exynos_drmif.h
+
+pkgconfigdir = @pkgconfigdir@
+pkgconfig_DATA = libdrm_exynos.pc
diff --git a/exynos/exynos_drm.c b/exynos/exynos_drm.c
new file mode 100644 (file)
index 0000000..dea4d4a
--- /dev/null
@@ -0,0 +1,427 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ *
+ * Authors:
+ *    Inki Dae <inki.dae@samsung.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sys/mman.h>
+#include <linux/stddef.h>
+
+#include <xf86drm.h>
+
+#include "exynos_drm.h"
+#include "exynos_drmif.h"
+
+/*
+ * Create exynos drm device object.
+ *
+ * @fd: file descriptor to exynos drm driver opened.
+ *
+ * if true, return the device object else NULL.
+ */
+struct exynos_device * exynos_device_create(int fd)
+{
+       struct exynos_device *dev;
+
+       dev = calloc(sizeof(*dev), 1);
+       if (!dev) {
+               fprintf(stderr, "failed to create device[%s].\n",
+                               strerror(errno));
+               return NULL;
+       }
+
+       dev->fd = fd;
+
+       return dev;
+}
+
+/*
+ * Destroy exynos drm device object
+ *
+ * @dev: exynos drm device object.
+ */
+void exynos_device_destroy(struct exynos_device *dev)
+{
+       free(dev);
+}
+
+/*
+ * Create a exynos buffer object to exynos drm device.
+ *
+ * @dev: exynos drm device object.
+ * @size: user-desired size.
+ * flags: user-desired memory type.
+ *     user can set one or more types among several types to memory
+ *     allocation and cache attribute types. and as default,
+ *     EXYNOS_BO_NONCONTIG and EXYNOS-BO_NONCACHABLE types would
+ *     be used.
+ *
+ * if true, return a exynos buffer object else NULL.
+ */
+struct exynos_bo * exynos_bo_create(struct exynos_device *dev,
+                                               size_t size, uint32_t flags)
+{
+       struct exynos_bo *bo;
+       struct drm_exynos_gem_create req = {
+               .size = size,
+               .flags = flags,
+       };
+
+       if (size == 0) {
+               fprintf(stderr, "invalid size.\n");
+               goto fail;
+       }
+
+       bo = calloc(sizeof(*bo), 1);
+       if (!bo) {
+               fprintf(stderr, "failed to create bo[%s].\n",
+                               strerror(errno));
+               goto err_free_bo;
+       }
+
+       bo->dev = dev;
+
+       if (drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_CREATE, &req)){
+               fprintf(stderr, "failed to create gem object[%s].\n",
+                               strerror(errno));
+               goto err_free_bo;
+       }
+
+       bo->handle = req.handle;
+       bo->size = size;
+       bo->flags = flags;
+
+       return bo;
+
+err_free_bo:
+       free(bo);
+fail:
+       return NULL;
+}
+
+/*
+ * Get information to gem region allocated.
+ *
+ * @dev: exynos drm device object.
+ * @handle: gem handle to request gem info.
+ * @size: size to gem object and returned by kernel side.
+ * @flags: gem flags to gem object and returned by kernel side.
+ *
+ * with this function call, you can get flags and size to gem handle
+ * through bo object.
+ *
+ * if true, return 0 else negative.
+ */
+int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle,
+                       size_t *size, uint32_t *flags)
+{
+       int ret;
+       struct drm_exynos_gem_info req = {
+               .handle = handle,
+       };
+
+       ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_GET, &req);
+       if (ret < 0) {
+               fprintf(stderr, "failed to get gem object information[%s].\n",
+                               strerror(errno));
+               return ret;
+       }
+
+       *size = req.size;
+       *flags = req.flags;
+
+       return 0;
+}
+
+/*
+ * Destroy a exynos buffer object.
+ *
+ * @bo: a exynos buffer object to be destroyed.
+ */
+void exynos_bo_destroy(struct exynos_bo *bo)
+{
+       if (!bo)
+               return;
+
+       if (bo->vaddr)
+               munmap(bo->vaddr, bo->size);
+
+       if (bo->handle) {
+               struct drm_gem_close req = {
+                       .handle = bo->handle,
+               };
+
+               drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+       }
+
+       free(bo);
+}
+
+
+/*
+ * Get a exynos buffer object from a gem global object name.
+ *
+ * @dev: a exynos device object.
+ * @name: a gem global object name exported by another process.
+ *
+ * this interface is used to get a exynos buffer object from a gem
+ * global object name sent by another process for buffer sharing.
+ *
+ * if true, return a exynos buffer object else NULL.
+ *
+ */
+struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name)
+{
+       struct exynos_bo *bo;
+       struct drm_gem_open req = {
+               .name = name,
+       };
+
+       bo = calloc(sizeof(*bo), 1);
+       if (!bo) {
+               fprintf(stderr, "failed to allocate bo[%s].\n",
+                               strerror(errno));
+               return NULL;
+       }
+
+       if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
+               fprintf(stderr, "failed to open gem object[%s].\n",
+                               strerror(errno));
+               goto err_free_bo;
+       }
+
+       bo->dev = dev;
+       bo->name = name;
+       bo->handle = req.handle;
+
+       return bo;
+
+err_free_bo:
+       free(bo);
+       return NULL;
+}
+
+/*
+ * Get a gem global object name from a gem object handle.
+ *
+ * @bo: a exynos buffer object including gem handle.
+ * @name: a gem global object name to be got by kernel driver.
+ *
+ * this interface is used to get a gem global object name from a gem object
+ * handle to a buffer that wants to share it with another process.
+ *
+ * if true, return 0 else negative.
+ */
+int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name)
+{
+       if (!bo->name) {
+               struct drm_gem_flink req = {
+                       .handle = bo->handle,
+               };
+               int ret;
+
+               ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
+               if (ret) {
+                       fprintf(stderr, "failed to get gem global name[%s].\n",
+                                       strerror(errno));
+                       return ret;
+               }
+
+               bo->name = req.name;
+       }
+
+       *name = bo->name;
+
+       return 0;
+}
+
+uint32_t exynos_bo_handle(struct exynos_bo *bo)
+{
+       return bo->handle;
+}
+
+/*
+ * Mmap a buffer to user space.
+ *
+ * @bo: a exynos buffer object including a gem object handle to be mmapped
+ *     to user space.
+ *
+ * if true, user pointer mmaped else NULL.
+ */
+void *exynos_bo_map(struct exynos_bo *bo)
+{
+       if (!bo->vaddr) {
+               struct exynos_device *dev = bo->dev;
+               struct drm_exynos_gem_mmap req = {
+                       .handle = bo->handle,
+                       .size   = bo->size,
+               };
+               int ret;
+
+               ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_MMAP, &req);
+               if (ret) {
+                       fprintf(stderr, "failed to mmap[%s].\n",
+                               strerror(errno));
+                       return NULL;
+               }
+
+               bo->vaddr = req.mapped;
+       }
+
+       return bo->vaddr;
+}
+
+/*
+ * Get a gem handle to user address space.
+ *
+ * @dev: a exynos device object.
+ * @vaddr: user space address to be imported into gem.
+ * @size: size to user space to be imported into gem.
+ * @handle: gem handle to gem object imported from user address and
+ *     returned by kernel side.
+ *
+ * if true, return 0 else negative.
+ */
+int exynos_userptr(struct exynos_device *dev, uint64_t vaddr,
+                       size_t size, uint32_t *handle)
+{
+       int ret;
+       struct drm_exynos_gem_userptr req = {
+               .userptr        = vaddr,
+               .size           = size,
+       };
+
+       ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_GEM_USERPTR, &req);
+       if (ret) {
+               fprintf(stderr, "failed to mmap[%s].\n",
+                       strerror(errno));
+               return ret;
+       }
+
+       *handle = req.handle;
+       return 0;
+}
+
+/*
+ * Export gem object to dmabuf as file descriptor.
+ *
+ * @dev: a exynos device object.
+ * @handle: gem handle to be exported into dmabuf as file descriptor.
+ * @fd: file descriptor to dmabuf exported from gem handle and
+ *     returned by kernel side.
+ *
+ * if true, return 0 else negative.
+ */
+int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle,
+                                       int *fd)
+{
+       int ret;
+       struct drm_prime_handle req = {
+               .handle = handle,
+       };
+
+       ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_HANDLE_TO_FD, &req);
+       if (ret) {
+               fprintf(stderr, "failed to mmap[%s].\n",
+                       strerror(errno));
+               return ret;
+       }
+
+       *fd = req.fd;
+       return 0;
+}
+
+/*
+ * Import file descriptor into gem handle.
+ *
+ * @dev: a exynos device object.
+ * @fd: file descriptor exported into dmabuf.
+ * @handle: gem handle to gem object imported from file descriptor
+ *     and returned by kernel side.
+ *
+ * if true, return 0 else negative.
+ */
+int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd,
+                                       uint32_t *handle)
+{
+       int ret;
+       struct drm_prime_handle req = {
+               .fd     = fd,
+       };
+
+       ret = drmIoctl(dev->fd, DRM_IOCTL_PRIME_FD_TO_HANDLE, &req);
+       if (ret) {
+               fprintf(stderr, "failed to mmap[%s].\n",
+                       strerror(errno));
+               return ret;
+       }
+
+       *handle = req.handle;
+       return 0;
+}
+
+
+
+/*
+ * Request Wireless Display connection or disconnection.
+ *
+ * @dev: a exynos device object.
+ * @connect: indicate whether connectoin or disconnection request.
+ * @ext: indicate whether edid data includes extentions data or not.
+ * @edid: a pointer to edid data from Wireless Display device.
+ *
+ * this interface is used to request Virtual Display driver connection or
+ * disconnection. for this, user should get a edid data from the Wireless
+ * Display device and then send that data to kernel driver with connection
+ * request
+ *
+ * if true, return 0 else negative.
+ */
+int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect,
+                               uint32_t ext, void *edid)
+{
+       struct drm_exynos_vidi_connection req = {
+               .connection     = connect,
+               .extensions     = ext,
+               .edid           = edid,
+       };
+       int ret;
+
+       ret = drmIoctl(dev->fd, DRM_IOCTL_EXYNOS_VIDI_CONNECTION, &req);
+       if (ret) {
+               fprintf(stderr, "failed to request vidi connection[%s].\n",
+                               strerror(errno));
+               return ret;
+       }
+
+       return 0;
+}
diff --git a/exynos/exynos_drm.h b/exynos/exynos_drm.h
new file mode 100644 (file)
index 0000000..580d0b7
--- /dev/null
@@ -0,0 +1,481 @@
+/* exynos_drm.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ * Authors:
+ *     Inki Dae <inki.dae@samsung.com>
+ *     Joonyoung Shim <jy0922.shim@samsung.com>
+ *     Seung-Woo Kim <sw0312.kim@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef _EXYNOS_DRM_H_
+#define _EXYNOS_DRM_H_
+
+#include "drm.h"
+
+/**
+ * User-desired buffer creation information structure.
+ *
+ * @size: user-desired memory allocation size.
+ *     - this size value would be page-aligned internally.
+ * @flags: user request for setting memory type or cache attributes.
+ * @handle: returned a handle to created gem object.
+ *     - this handle will be set by gem module of kernel side.
+ */
+struct drm_exynos_gem_create {
+       uint64_t size;
+       unsigned int flags;
+       unsigned int handle;
+};
+
+/**
+ * A structure for getting buffer offset.
+ *
+ * @handle: a pointer to gem object created.
+ * @pad: just padding to be 64-bit aligned.
+ * @offset: relatived offset value of the memory region allocated.
+ *     - this value should be set by user.
+ */
+struct drm_exynos_gem_map_off {
+       unsigned int handle;
+       unsigned int pad;
+       uint64_t offset;
+};
+
+/**
+ * A structure for mapping buffer.
+ *
+ * @handle: a handle to gem object created.
+ * @pad: just padding to be 64-bit aligned.
+ * @size: memory size to be mapped.
+ * @mapped: having user virtual address mmaped.
+ *     - this variable would be filled by exynos gem module
+ *     of kernel side with user virtual address which is allocated
+ *     by do_mmap().
+ */
+struct drm_exynos_gem_mmap {
+       unsigned int handle;
+       unsigned int pad;
+       uint64_t size;
+       uint64_t mapped;
+};
+
+/**
+ * User-requested user space importing structure
+ *
+ * @userptr: user space address allocated by malloc.
+ * @size: size to the buffer allocated by malloc.
+ * @flags: indicate user-desired cache attribute to map the allocated buffer
+ *     to kernel space.
+ * @handle: a returned handle to created gem object.
+ *     - this handle will be set by gem module of kernel side.
+ */
+struct drm_exynos_gem_userptr {
+       uint64_t userptr;
+       uint64_t size;
+       unsigned int flags;
+       unsigned int handle;
+};
+
+/**
+ * A structure to gem information.
+ *
+ * @handle: a handle to gem object created.
+ * @flags: flag value including memory type and cache attribute and
+ *     this value would be set by driver.
+ * @size: size to memory region allocated by gem and this size would
+ *     be set by driver.
+ */
+struct drm_exynos_gem_info {
+       unsigned int handle;
+       unsigned int flags;
+       uint64_t size;
+};
+
+/**
+ * A structure to userptr limited information.
+ *
+ * @userptr_limit: maximum size to userptr buffer.
+ *     the buffer could be allocated by unprivileged user using malloc()
+ *     and the size of the buffer would be limited as userptr_limit value.
+ * @pad: just padding to be 64-bit aligned.
+ */
+struct drm_exynos_user_limit {
+       unsigned int userptr_limit;
+       unsigned int pad;
+};
+
+/**
+ * A structure for user connection request of virtual display.
+ *
+ * @connection: indicate whether doing connetion or not by user.
+ * @extensions: if this value is 1 then the vidi driver would need additional
+ *     128bytes edid data.
+ * @edid: the edid data pointer from user side.
+ */
+struct drm_exynos_vidi_connection {
+       unsigned int connection;
+       unsigned int extensions;
+       uint64_t *edid;
+};
+
+/**
+ * A structure for ump.
+ *
+ * @gem_handle: a pointer to gem object created.
+ * @secure_id: ump secure id and this value would be filled
+ *             by kernel side.
+ */
+struct drm_exynos_gem_ump {
+       unsigned int gem_handle;
+       unsigned int secure_id;
+};
+
+
+/* temporary codes for legacy fimc and mfc drivers. */
+
+/**
+ * A structure for getting physical address corresponding to a gem handle.
+ */
+struct drm_exynos_gem_get_phy {
+       unsigned int gem_handle;
+       unsigned int pad;
+       uint64_t size;
+       uint64_t phy_addr;
+};
+
+/**
+ * A structure for importing physical memory to a gem.
+ */
+struct drm_exynos_gem_phy_imp {
+       uint64_t phy_addr;
+       uint64_t size;
+       unsigned int gem_handle;
+       unsigned int pad;
+};
+
+/* indicate cache units. */
+enum e_drm_exynos_gem_cache_sel {
+       EXYNOS_DRM_L1_CACHE             = 1 << 0,
+       EXYNOS_DRM_L2_CACHE             = 1 << 1,
+       EXYNOS_DRM_ALL_CORES            = 1 << 2,
+       EXYNOS_DRM_ALL_CACHES           = EXYNOS_DRM_L1_CACHE |
+                                               EXYNOS_DRM_L2_CACHE,
+       EXYNOS_DRM_ALL_CACHES_CORES     = EXYNOS_DRM_L1_CACHE |
+                                               EXYNOS_DRM_L2_CACHE |
+                                               EXYNOS_DRM_ALL_CORES,
+       EXYNOS_DRM_CACHE_SEL_MASK       = EXYNOS_DRM_ALL_CACHES_CORES
+};
+
+/* indicate cache operation types. */
+enum e_drm_exynos_gem_cache_op {
+       EXYNOS_DRM_CACHE_INV_ALL        = 1 << 3,
+       EXYNOS_DRM_CACHE_INV_RANGE      = 1 << 4,
+       EXYNOS_DRM_CACHE_CLN_ALL        = 1 << 5,
+       EXYNOS_DRM_CACHE_CLN_RANGE      = 1 << 6,
+       EXYNOS_DRM_CACHE_FSH_ALL        = EXYNOS_DRM_CACHE_INV_ALL |
+                                               EXYNOS_DRM_CACHE_CLN_ALL,
+       EXYNOS_DRM_CACHE_FSH_RANGE      = EXYNOS_DRM_CACHE_INV_RANGE |
+                                               EXYNOS_DRM_CACHE_CLN_RANGE,
+       EXYNOS_DRM_CACHE_OP_MASK        = EXYNOS_DRM_CACHE_FSH_ALL |
+                                               EXYNOS_DRM_CACHE_FSH_RANGE
+};
+
+/* memory type definitions. */
+enum e_drm_exynos_gem_mem_type {
+       /* Physically Continuous memory and used as default. */
+       EXYNOS_BO_CONTIG        = 0 << 0,
+       /* Physically Non-Continuous memory. */
+       EXYNOS_BO_NONCONTIG     = 1 << 0,
+       /* non-cachable mapping and used as default. */
+       EXYNOS_BO_NONCACHABLE   = 0 << 1,
+       /* cachable mapping. */
+       EXYNOS_BO_CACHABLE      = 1 << 1,
+       /* write-combine mapping. */
+       EXYNOS_BO_WC            = 1 << 2,
+       /* user space memory allocated by malloc. */
+       EXYNOS_BO_USERPTR       = 1 << 3,
+       EXYNOS_BO_MASK          = EXYNOS_BO_NONCONTIG | EXYNOS_BO_CACHABLE |
+                                       EXYNOS_BO_WC | EXYNOS_BO_USERPTR
+};
+
+/**
+ * A structure for cache operation.
+ *
+ * @usr_addr: user space address.
+ *     P.S. it SHOULD BE user space.
+ * @size: buffer size for cache operation.
+ * @flags: select cache unit and cache operation.
+ * @gem_handle: a handle to a gem object.
+ *     this gem handle is needed for cache range operation to L2 cache.
+ */
+struct drm_exynos_gem_cache_op {
+       uint64_t usr_addr;
+       unsigned int size;
+       unsigned int flags;
+       unsigned int gem_handle;
+};
+
+struct drm_exynos_g2d_get_ver {
+       __u32   major;
+       __u32   minor;
+};
+
+struct drm_exynos_g2d_cmd {
+       __u32   offset;
+       __u32   data;
+};
+
+enum drm_exynos_g2d_event_type {
+       G2D_EVENT_NOT,
+       G2D_EVENT_NONSTOP,
+       G2D_EVENT_STOP,         /* not yet */
+};
+
+struct drm_exynos_g2d_set_cmdlist {
+       struct drm_exynos_g2d_cmd               *cmd;
+       struct drm_exynos_g2d_cmd               *cmd_gem;
+       __u32                                   cmd_nr;
+       __u32                                   cmd_gem_nr;
+
+       /* for g2d event */
+       __u64                                   user_data;
+       __u32                                   event_type;
+       __u32                                   reserved;
+};
+
+struct drm_exynos_g2d_exec {
+       __u32                                   async;
+       __u32                                   reserved;
+};
+
+/* definition of operations types */
+enum drm_exynos_ops_id {
+       EXYNOS_DRM_OPS_SRC,
+       EXYNOS_DRM_OPS_DST,
+       EXYNOS_DRM_OPS_MAX
+};
+
+/* definition of size */
+struct drm_exynos_sz {
+       __u32   hsize;
+       __u32   vsize;
+};
+
+/* definition of position */
+struct drm_exynos_pos {
+       __u32   x;
+       __u32   y;
+       __u32   w;
+       __u32   h;
+};
+
+/* definition of flip */
+enum drm_exynos_flip {
+       EXYNOS_DRM_FLIP_NONE = (0 << 0),
+       EXYNOS_DRM_FLIP_VERTICAL = (1 << 0),
+       EXYNOS_DRM_FLIP_HORIZONTAL = (1 << 1),
+};
+
+/* definition of rotation degree */
+enum drm_exynos_degree {
+       EXYNOS_DRM_DEGREE_0,
+       EXYNOS_DRM_DEGREE_90,
+       EXYNOS_DRM_DEGREE_180,
+       EXYNOS_DRM_DEGREE_270,
+};
+
+/* definition of planar */
+enum drm_exynos_planer {
+       EXYNOS_DRM_PLANAR_Y,
+       EXYNOS_DRM_PLANAR_CB,
+       EXYNOS_DRM_PLANAR_CR,
+       EXYNOS_DRM_PLANAR_MAX
+};
+
+/**
+ * A structure for ipp config.
+ *
+ * @ops_id: property of operation directions.
+ * @flip: property of mirror, flip.
+ * @degree: property of rotation degree.
+ * @fmt: property of image format.
+ * @sz: property of image size.
+ * @pos: property of image position(src-cropped,dst-scaler).
+ */
+struct drm_exynos_ipp_config {
+       enum drm_exynos_ops_id ops_id;
+       enum drm_exynos_flip    flip;
+       enum drm_exynos_degree  degree;
+       __u32   fmt;
+       struct drm_exynos_sz    sz;
+       struct drm_exynos_pos   pos;
+};
+
+/**
+ * A structure for ipp property.
+ *
+ * @config: source, destination config.
+ */
+struct drm_exynos_ipp_property {
+       struct drm_exynos_ipp_config config[EXYNOS_DRM_OPS_MAX];
+};
+
+/* command of ipp operations */
+enum drm_exynos_ipp_cmd {
+       IPP_CMD_NONE,
+       IPP_CMD_M2M,
+       IPP_CMD_WB,
+       IPP_CMD_OUT,
+       IPP_CMD_MAX
+};
+
+/* definition of buffer control */
+enum drm_exynos_ipp_buf_ctrl {
+       IPP_BUF_CTRL_MAP,
+       IPP_BUF_CTRL_UNMAP,
+       IPP_BUF_CTRL_QUEUE,
+       IPP_BUF_CTRL_DEQUEUE
+};
+
+/**
+ * A structure for ipp buffer operations.
+ *
+ * @ops_id: operation directions.
+ * @ctrl: buffer control.
+ * @id: index of buffer.
+ * @handle: Y, Cb, Cr each planar handle.
+ * @user_data: user data.
+ */
+struct drm_exynos_ipp_buf {
+       enum drm_exynos_ops_id  ops_id;
+       enum drm_exynos_ipp_buf_ctrl    buf_ctrl;
+       __u32   id;
+       __u32   handle[EXYNOS_DRM_PLANAR_MAX];
+       __u64   user_data;
+};
+
+/**
+ * A structure for ipp start/stop operations.
+ *
+ * @cmd: command id.
+ * @use: use ipp device.
+ */
+struct drm_exynos_ipp_ctrl {
+       enum drm_exynos_ipp_cmd cmd;
+       __u32   use;
+};
+
+#define DRM_EXYNOS_GEM_CREATE          0x00
+#define DRM_EXYNOS_GEM_MAP_OFFSET      0x01
+#define DRM_EXYNOS_GEM_MMAP            0x02
+#define DRM_EXYNOS_GEM_USERPTR         0x03
+#define DRM_EXYNOS_GEM_GET             0x04
+#define DRM_EXYNOS_USER_LIMIT          0x05
+#define DRM_EXYNOS_VIDI_CONNECTION     0x07
+
+/* temporary ioctl command. */
+#define DRM_EXYNOS_GEM_EXPORT_UMP      0x10
+#define DRM_EXYNOS_GEM_CACHE_OP                0x12
+
+#define DRM_EXYNOS_GEM_GET_PHY         0x13
+#define DRM_EXYNOS_GEM_PHY_IMP         0x14
+
+/* G2D */
+#define DRM_EXYNOS_G2D_GET_VER         0x20
+#define DRM_EXYNOS_G2D_SET_CMDLIST     0x21
+#define DRM_EXYNOS_G2D_EXEC            0x22
+
+/* IPP - Image Post Processing */
+#define DRM_EXYNOS_IPP_PROPERTY                0x30
+#define DRM_EXYNOS_IPP_BUF                     0x31
+#define DRM_EXYNOS_IPP_CTRL                    0x32
+
+#define DRM_IOCTL_EXYNOS_GEM_CREATE            DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)
+
+#define DRM_IOCTL_EXYNOS_GEM_MAP_OFFSET        DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_MAP_OFFSET, struct drm_exynos_gem_map_off)
+
+#define DRM_IOCTL_EXYNOS_GEM_MMAP      DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap)
+
+#define DRM_IOCTL_EXYNOS_GEM_USERPTR   DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_USERPTR, struct drm_exynos_gem_userptr)
+
+#define DRM_IOCTL_EXYNOS_GEM_GET       DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_GET,     struct drm_exynos_gem_info)
+
+#define DRM_IOCTL_EXYNOS_USER_LIMIT    DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_USER_LIMIT,  struct drm_exynos_user_limit)
+
+#define DRM_IOCTL_EXYNOS_GEM_EXPORT_UMP        DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_EXPORT_UMP, struct drm_exynos_gem_ump)
+
+#define DRM_IOCTL_EXYNOS_GEM_CACHE_OP  DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_CACHE_OP, struct drm_exynos_gem_cache_op)
+
+/* temporary ioctl command. */
+#define DRM_IOCTL_EXYNOS_GEM_GET_PHY   DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_GET_PHY, struct drm_exynos_gem_get_phy)
+#define DRM_IOCTL_EXYNOS_GEM_PHY_IMP   DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_GEM_PHY_IMP, struct drm_exynos_gem_phy_imp)
+
+#define DRM_IOCTL_EXYNOS_VIDI_CONNECTION       DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_VIDI_CONNECTION, struct drm_exynos_vidi_connection)
+
+#define DRM_IOCTL_EXYNOS_G2D_GET_VER           DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_G2D_GET_VER, struct drm_exynos_g2d_get_ver)
+#define DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST       DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_G2D_SET_CMDLIST, struct drm_exynos_g2d_set_cmdlist)
+#define DRM_IOCTL_EXYNOS_G2D_EXEC              DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_G2D_EXEC, struct drm_exynos_g2d_exec)
+
+#define DRM_IOCTL_EXYNOS_IPP_PROPERTY  DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_IPP_PROPERTY, struct drm_exynos_ipp_property)
+#define DRM_IOCTL_EXYNOS_IPP_BUF       DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_IPP_BUF, struct drm_exynos_ipp_buf)
+#define DRM_IOCTL_EXYNOS_IPP_CTRL              DRM_IOWR(DRM_COMMAND_BASE + \
+               DRM_EXYNOS_IPP_CTRL, struct drm_exynos_ipp_ctrl)
+
+/* EXYNOS specific events */
+#define DRM_EXYNOS_G2D_EVENT           0x80000000
+#define DRM_EXYNOS_IPP_EVENT           0x80000001
+
+struct drm_exynos_g2d_event {
+       struct drm_event        base;
+       __u64                   user_data;
+       __u32                   tv_sec;
+       __u32                   tv_usec;
+       __u32                   cmdlist_no;
+       __u32                   reserved;
+};
+
+struct drm_exynos_ipp_event {
+       struct drm_event        base;
+       __u64                   user_data;
+       __u32                   tv_sec;
+       __u32                   tv_usec;
+       __u32                   buf_idx;
+       __u32                   reserved;
+};
+
+#endif
diff --git a/exynos/exynos_drmif.h b/exynos/exynos_drmif.h
new file mode 100644 (file)
index 0000000..24d2f64
--- /dev/null
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co., Ltd.
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ *
+ * Authors:
+ *    Inki Dae <inki.dae@samsung.com>
+ */
+
+#ifndef EXYNOS_DRMIF_H_
+#define EXYNOS_DRMIF_H_
+
+#include <xf86drm.h>
+#include <stdint.h>
+#include "exynos_drm.h"
+
+struct exynos_device {
+       int fd;
+};
+
+/*
+ * Exynos Buffer Object structure.
+ *
+ * @dev: exynos device object allocated.
+ * @handle: a gem handle to gem object created.
+ * @flags: indicate memory allocation and cache attribute types.
+ * @fd: file descriptor exported into dmabuf.
+ * @size: size to the buffer created.
+ * @vaddr: user space address to a gem buffer mmaped.
+ * @name: a gem global handle from flink request.
+ */
+struct exynos_bo {
+       struct exynos_device    *dev;
+       uint32_t                handle;
+       uint32_t                flags;
+       int                     fd;
+       size_t                  size;
+       void                    *vaddr;
+       uint32_t                name;
+};
+
+/*
+ * device related functions:
+ */
+struct exynos_device * exynos_device_create(int fd);
+void exynos_device_destroy(struct exynos_device *dev);
+
+/*
+ * buffer-object related functions:
+ */
+struct exynos_bo * exynos_bo_create(struct exynos_device *dev,
+               size_t size, uint32_t flags);
+int exynos_bo_get_info(struct exynos_device *dev, uint32_t handle,
+                       size_t *size, uint32_t *flags);
+void exynos_bo_destroy(struct exynos_bo *bo);
+struct exynos_bo * exynos_bo_from_name(struct exynos_device *dev, uint32_t name);
+int exynos_bo_get_name(struct exynos_bo *bo, uint32_t *name);
+uint32_t exynos_bo_handle(struct exynos_bo *bo);
+void * exynos_bo_map(struct exynos_bo *bo);
+int exynos_userptr(struct exynos_device *dev, uint64_t vaddr,
+                       size_t size, uint32_t *handle);
+int exynos_prime_handle_to_fd(struct exynos_device *dev, uint32_t handle,
+                                       int *fd);
+int exynos_prime_fd_to_handle(struct exynos_device *dev, int fd,
+                                       uint32_t *handle);
+
+/*
+ * Virtual Display related functions:
+ */
+int exynos_vidi_connection(struct exynos_device *dev, uint32_t connect,
+                               uint32_t ext, void *edid);
+
+#endif /* EXYNOS_DRMIF_H_ */
diff --git a/exynos/libdrm_exynos.pc.in b/exynos/libdrm_exynos.pc.in
new file mode 100644 (file)
index 0000000..5ce9118
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libdrm_exynos
+Description: Userspace interface to exynos kernel DRM services
+Version: 0.6
+Libs: -L${libdir} -ldrm_exynos
+Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/exynos
+Requires.private: libdrm
old mode 100755 (executable)
new mode 100644 (file)
index 965d4e5..2923ab4
@@ -36,8 +36,8 @@ klibdrminclude_HEADERS = \
        savage_drm.h \
        sis_drm.h \
        via_drm.h \
-       mach64_drm.h \
-       exynos_drm.h
+       mach64_drm.h
+
 
 if HAVE_VMWGFX
 klibdrminclude_HEADERS += vmwgfx_drm.h
index 8adb9d5..5e6cd29 100644 (file)
@@ -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'
@@ -686,6 +697,9 @@ struct drm_get_cap {
 #define DRM_IOCTL_SG_ALLOC             DRM_IOWR(0x38, struct drm_scatter_gather)
 #define DRM_IOCTL_SG_FREE              DRM_IOW( 0x39, struct drm_scatter_gather)
 
+#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_WAIT_VBLANK          DRM_IOWR(0x3a, union drm_wait_vblank)
 
 #define DRM_IOCTL_UPDATE_DRAW          DRM_IOW(0x3f, struct drm_update_draw)
@@ -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
index b1107cb..85facb0 100644 (file)
 #ifndef DRM_FOURCC_H
 #define DRM_FOURCC_H
 
-#include <linux/types.h>
+#include <inttypes.h>
 
-#define fourcc_code(a,b,c,d) ((__u32)(a) | ((__u32)(b) << 8) | \
-                             ((__u32)(c) << 16) | ((__u32)(d) << 24))
+#define fourcc_code(a,b,c,d) ((uint32_t)(a) | ((uint32_t)(b) << 8) | \
+                             ((uint32_t)(c) << 16) | ((uint32_t)(d) << 24))
 
 #define DRM_FORMAT_BIG_ENDIAN (1<<31) /* format is big endian instead of little endian */
 
old mode 100755 (executable)
new mode 100644 (file)
index 0a76ff9..c3f374d
@@ -162,6 +162,7 @@ struct drm_mode_get_plane_res {
 #define DRM_MODE_ENCODER_TMDS  2
 #define DRM_MODE_ENCODER_LVDS  3
 #define DRM_MODE_ENCODER_TVDAC 4
+#define DRM_MODE_ENCODER_VIRTUAL       5
 
 struct drm_mode_get_encoder {
        __u32 encoder_id;
@@ -199,6 +200,7 @@ struct drm_mode_get_encoder {
 #define DRM_MODE_CONNECTOR_HDMIB       12
 #define DRM_MODE_CONNECTOR_TV          13
 #define DRM_MODE_CONNECTOR_eDP         14
+#define DRM_MODE_CONNECTOR_VIRTUAL     15
 
 struct drm_mode_get_connector {
 
@@ -226,6 +228,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 +253,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;
@@ -341,7 +368,7 @@ struct drm_mode_mode_cmd {
 #define DRM_MODE_CURSOR_MOVE   (1<<1)
 
 /*
- * depending on the value in flags different members are used.
+ * depending on the value in flags diffrent members are used.
  *
  * CURSOR_BO uses
  *    crtc
@@ -410,31 +437,31 @@ struct drm_mode_crtc_page_flip {
 
 /* create a dumb scanout buffer */
 struct drm_mode_create_dumb {
-       uint32_t height;
-       uint32_t width;
-       uint32_t bpp;
-       uint32_t flags;
-       /* handle, pitch, size will be returned */
-       uint32_t handle;
-       uint32_t pitch;
-       uint64_t size;
+        __u32 height;
+        __u32 width;
+        __u32 bpp;
+        __u32 flags;
+        /* handle, pitch, size will be returned */
+        __u32 handle;
+        __u32 pitch;
+        __u64 size;
 };
 
 /* set up for mmap of a dumb scanout buffer */
 struct drm_mode_map_dumb {
-       /** Handle for the object being mapped. */
-       __u32 handle;
-       __u32 pad;
-       /**
-        * Fake offset to use for subsequent mmap call
-        *
-        * This is a fixed-size type for 32/64 compatibility.
-        */
-       __u64 offset;
+        /** Handle for the object being mapped. */
+        __u32 handle;
+        __u32 pad;
+        /**
+         * Fake offset to use for subsequent mmap call
+         *
+         * This is a fixed-size type for 32/64 compatibility.
+         */
+        __u64 offset;
 };
 
 struct drm_mode_destroy_dumb {
-       uint32_t handle;
+       __u32 handle;
 };
 
 #endif
diff --git a/include/drm/exynos_drm.h b/include/drm/exynos_drm.h
deleted file mode 100755 (executable)
index 99e64a8..0000000
+++ /dev/null
@@ -1,204 +0,0 @@
-/* exynos_drm.h
- *
- * Copyright (c) 2011 Samsung Electronics Co., Ltd.
- * Authors:
- *     Inki Dae <inki.dae@samsung.com>
- *     Joonyoung Shim <jy0922.shim@samsung.com>
- *     Seung-Woo Kim <sw0312.kim@samsung.com>
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the "Software"),
- * to deal in the Software without restriction, including without limitation
- * the rights to use, copy, modify, merge, publish, distribute, 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:
- *
- * The above copyright notice and this permission notice (including the next
- * paragraph) shall be included in all copies or substantial portions of the
- * Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
- * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
- * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
- * OTHER DEALINGS IN THE SOFTWARE.
- */
-
-#ifndef _EXYNOS_DRM_H_
-#define _EXYNOS_DRM_H_
-
-/**
- * User-desired buffer creation information structure.
- *
- * @size: user-desired memory allocation size.
- *     - this size value would be page-aligned internally.
- * @flags: user request for setting memory type or cache attributes.
- * @handle: returned a handle to created gem object.
- *     - this handle will be set by gem module of kernel side.
- */
-struct drm_exynos_gem_create {
-       uint64_t size;
-       unsigned int flags;
-       unsigned int handle;
-};
-
-/**
- * A structure for getting buffer offset.
- *
- * @handle: a pointer to gem object created.
- * @pad: just padding to be 64-bit aligned.
- * @offset: relatived offset value of the memory region allocated.
- *     - this value should be set by user.
- */
-struct drm_exynos_gem_map_off {
-       unsigned int handle;
-       unsigned int pad;
-       uint64_t offset;
-};
-
-/**
- * A structure for mapping buffer.
- *
- * @handle: a handle to gem object created.
- * @pad: just padding to be 64-bit aligned.
- * @size: memory size to be mapped.
- * @mapped: having user virtual address mmaped.
- *     - this variable would be filled by exynos gem module
- *     of kernel side with user virtual address which is allocated
- *     by do_mmap().
- */
-struct drm_exynos_gem_mmap {
-       unsigned int handle;
-       unsigned int pad;
-       uint64_t size;
-       uint64_t mapped;
-};
-
-/**
- * A structure for user connection request of virtual display.
- *
- * @connection: indicate whether doing connetion or not by user.
- * @extensions: if this value is 1 then the vidi driver would need additional
- *     128bytes edid data.
- * @pad: just padding to be 64-bit aligned.
- * @edid: the edid data pointer from user side.
- */
-struct drm_exynos_vidi_connection {
-       unsigned int connection;
-       unsigned int extensions;
-       unsigned int pad;
-       void *edid;
-};
-
-/**
- * A structure for ump.
- *
- * @gem_handle: a pointer to gem object created.
- * @secure_id: ump secure id and this value would be filled
- *             by kernel side.
- */
-struct drm_exynos_gem_ump {
-       unsigned int gem_handle;
-       unsigned int secure_id;
-};
-
-
-/* temporary codes for legacy fimc and mfc drivers. */
-
-/**
- * A structure for getting physical address corresponding to a gem handle.
- */
-struct drm_exynos_gem_get_phy {
-       unsigned int gem_handle;
-       unsigned int pad;
-       uint64_t size;
-       uint64_t phy_addr;
-};
-
-/**
- * A structure for importing physical memory to a gem.
- */
-struct drm_exynos_gem_phy_imp {
-       uint64_t phy_addr;
-       uint64_t size;
-       unsigned int gem_handle;
-       unsigned int pad;
-};
-
-/* indicate cache units. */
-enum e_drm_exynos_gem_cache_sel {
-       EXYNOS_DRM_L1_CACHE     = 1,
-       EXYNOS_DRM_L2_CACHE     = 2,
-       EXYNOS_DRM_ALL_CACHE    = 3
-};
-
-/* indicate cache operation types. */
-enum e_drm_exynos_gem_cache_op {
-       EXYNOS_DRM_CACHE_INV    = 4,
-       EXYNOS_DRM_CACHE_CLN    = 8,
-       EXYNOS_DRM_CACHE_FSH    = 0xC
-};
-
-/**
- * A structure for cache operation.
- *
- * @usr_addr: user space address.
- *     P.S. it SHOULD BE user space.
- * @size: buffer size for cache operation.
- * @flags: select cache unit and cache operation.
- */
-struct drm_exynos_gem_cache_op {
-       uint64_t usr_addr;
-       unsigned int size;
-       unsigned int flags;
-};
-
-struct drm_exynos_plane_set_zpos {
-       __u32 plane_id;
-       __s32 zpos;
-};
-
-#define DRM_EXYNOS_GEM_CREATE          0x00
-#define DRM_EXYNOS_GEM_MAP_OFFSET      0x01
-#define DRM_EXYNOS_GEM_MMAP            0x02
-/* Reserved 0x03 ~ 0x05 for exynos specific gem ioctl */
-#define DRM_EXYNOS_PLANE_SET_ZPOS      0x06
-#define DRM_EXYNOS_VIDI_CONNECTION     0x07
-
-/* temporary ioctl command. */
-#define DRM_EXYNOS_GEM_EXPORT_UMP      0x10
-#define DRM_EXYNOS_GEM_CACHE_OP                0x12
-
-#define DRM_EXYNOS_GEM_GET_PHY         0x13
-#define DRM_EXYNOS_GEM_PHY_IMP         0x14
-
-#define DRM_IOCTL_EXYNOS_GEM_CREATE            DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_GEM_CREATE, struct drm_exynos_gem_create)
-
-#define DRM_IOCTL_EXYNOS_GEM_MAP_OFFSET        DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_GEM_MAP_OFFSET, struct drm_exynos_gem_map_off)
-
-#define DRM_IOCTL_EXYNOS_GEM_MMAP      DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_GEM_MMAP, struct drm_exynos_gem_mmap)
-
-#define DRM_IOCTL_EXYNOS_GEM_EXPORT_UMP        DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_GEM_EXPORT_UMP, struct drm_exynos_gem_ump)
-
-#define DRM_IOCTL_EXYNOS_GEM_CACHE_OP  DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_GEM_CACHE_OP, struct drm_exynos_gem_cache_op)
-
-/* temporary ioctl command. */
-#define DRM_IOCTL_EXYNOS_GEM_GET_PHY   DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_GEM_GET_PHY, struct drm_exynos_gem_get_phy)
-#define DRM_IOCTL_EXYNOS_GEM_PHY_IMP   DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_GEM_PHY_IMP, struct drm_exynos_gem_phy_imp)
-
-#define DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS        DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_PLANE_SET_ZPOS, struct drm_exynos_plane_set_zpos)
-
-#define DRM_IOCTL_EXYNOS_VIDI_CONNECTION       DRM_IOWR(DRM_COMMAND_BASE + \
-               DRM_EXYNOS_VIDI_CONNECTION, struct drm_exynos_vidi_connection)
-
-#endif
index adc2392..4931107 100644 (file)
@@ -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
@@ -189,6 +190,9 @@ typedef struct _drm_i915_sarea {
 #define DRM_I915_OVERLAY_PUT_IMAGE     0x27
 #define DRM_I915_OVERLAY_ATTRS 0x28
 #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_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)
@@ -228,8 +232,11 @@ typedef struct _drm_i915_sarea {
 #define DRM_IOCTL_I915_GEM_GET_APERTURE        DRM_IOR  (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
 #define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_i915_get_pipe_from_crtc_id)
 #define DRM_IOCTL_I915_GEM_MADVISE     DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)
-#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE       DRM_IOW(DRM_COMMAND_BASE + DRM_IOCTL_I915_OVERLAY_ATTRS, struct drm_intel_overlay_put_image)
+#define DRM_IOCTL_I915_OVERLAY_PUT_IMAGE       DRM_IOW(DRM_COMMAND_BASE + DRM_I915_OVERLAY_PUT_IMAGE, struct drm_intel_overlay_put_image)
 #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)
 
 /* Allow drivers to submit batchbuffers directly to hardware, relying
  * on the security mechanisms provided by hardware.
@@ -282,6 +289,10 @@ typedef struct drm_i915_irq_wait {
 #define I915_PARAM_HAS_COHERENT_RINGS   13
 #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_ALIASING_PPGTT   18
+#define I915_PARAM_HAS_WAIT_TIMEOUT     19
 
 typedef struct drm_i915_getparam {
        int param;
@@ -644,6 +655,9 @@ struct drm_i915_gem_execbuffer2 {
        __u64 rsvd2;
 };
 
+/** Resets the SO write offset registers for transform feedback on gen7. */
+#define I915_EXEC_GEN7_SOL_RESET       (1<<8)
+
 struct drm_i915_gem_pin {
        /** Handle of the buffer to be pinned. */
        __u32 handle;
@@ -835,4 +849,44 @@ struct drm_intel_overlay_attrs {
        __u32 gamma5;
 };
 
+/*
+ * Intel sprite handling
+ *
+ * Color keying works with a min/mask/max tuple.  Both source and destination
+ * color keying is allowed.
+ *
+ * Source keying:
+ * Sprite pixels within the min & max values, masked against the color channels
+ * specified in the mask field, will be transparent.  All other pixels will
+ * be displayed on top of the primary plane.  For RGB surfaces, only the min
+ * and mask fields will be used; ranged compares are not allowed.
+ *
+ * Destination keying:
+ * Primary plane pixels that match the min value, masked against the color
+ * channels specified in the mask field, will be replaced by corresponding
+ * pixels from the sprite plane.
+ *
+ * Note that source & destination keying are exclusive; only one can be
+ * active on a given plane.
+ */
+
+#define I915_SET_COLORKEY_NONE         (1<<0) /* disable color key matching */
+#define I915_SET_COLORKEY_DESTINATION  (1<<1)
+#define I915_SET_COLORKEY_SOURCE       (1<<2)
+struct drm_intel_sprite_colorkey {
+       __u32 plane_id;
+       __u32 min_value;
+       __u32 channel_mask;
+       __u32 max_value;
+       __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;
+};
+
 #endif                         /* _I915_DRM_H_ */
index 3b762d6..00d66b3 100644 (file)
@@ -802,13 +802,23 @@ struct drm_radeon_gem_create {
        uint32_t        flags;
 };
 
-#define RADEON_TILING_MACRO       0x1
-#define RADEON_TILING_MICRO       0x2
-#define RADEON_TILING_SWAP_16BIT  0x4
-#define RADEON_TILING_SWAP_32BIT  0x8
-#define RADEON_TILING_SURFACE     0x10 /* this object requires a surface
-                                       * when mapped - i.e. front buffer */
-#define RADEON_TILING_MICRO_SQUARE 0x20
+#define RADEON_TILING_MACRO                            0x1
+#define RADEON_TILING_MICRO                            0x2
+#define RADEON_TILING_SWAP_16BIT                       0x4
+#define RADEON_TILING_SWAP_32BIT                       0x8
+/* this object requires a surface when mapped - i.e. front buffer */
+#define RADEON_TILING_SURFACE                          0x10
+#define RADEON_TILING_MICRO_SQUARE                     0x20
+#define RADEON_TILING_EG_BANKW_SHIFT                   8
+#define RADEON_TILING_EG_BANKW_MASK                    0xf
+#define RADEON_TILING_EG_BANKH_SHIFT                   12
+#define RADEON_TILING_EG_BANKH_MASK                    0xf
+#define RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT       16
+#define RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK                0xf
+#define RADEON_TILING_EG_TILE_SPLIT_SHIFT              24
+#define RADEON_TILING_EG_TILE_SPLIT_MASK               0xf
+#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_SHIFT      28
+#define RADEON_TILING_EG_STENCIL_TILE_SPLIT_MASK       0xf
 
 struct drm_radeon_gem_set_tiling {
        uint32_t        handle;
diff --git a/intel/.gitignore b/intel/.gitignore
new file mode 100644 (file)
index 0000000..528b408
--- /dev/null
@@ -0,0 +1 @@
+test_decode
index 7a44aaf..dc01a96 100644 (file)
@@ -28,24 +28,55 @@ AM_CFLAGS = \
        -I$(top_srcdir)/intel \
        $(PTHREADSTUBS_CFLAGS) \
        $(PCIACCESS_CFLAGS) \
+       $(VALGRIND_CFLAGS) \
        -I$(top_srcdir)/include/drm
 
 libdrm_intel_la_LTLIBRARIES = libdrm_intel.la
 libdrm_intel_ladir = $(libdir)
 libdrm_intel_la_LDFLAGS = -version-number 1:0:0 -no-undefined
-libdrm_intel_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@ @PCIACCESS_LIBS@ @CLOCK_LIB@
+libdrm_intel_la_LIBADD = ../libdrm.la \
+       @PTHREADSTUBS_LIBS@ \
+       @PCIACCESS_LIBS@ \
+       @CLOCK_LIB@
 
 libdrm_intel_la_SOURCES = \
        intel_bufmgr.c \
        intel_bufmgr_priv.h \
        intel_bufmgr_fake.c \
        intel_bufmgr_gem.c \
+       intel_decode.c \
        intel_chipset.h \
        mm.c \
        mm.h
 
+intel_bufmgr_gem_o_CFLAGS = $(AM_CFLAGS) -c99
+
 libdrm_intelincludedir = ${includedir}/libdrm
 libdrm_intelinclude_HEADERS = intel_bufmgr.h \
+                             intel_aub.h \
                              intel_debug.h
 
+# This may be interesting even outside of "make check", due to the -dump option.
+noinst_PROGRAMS = test_decode
+
+BATCHES = \
+       tests/gen4-3d.batch \
+       tests/gm45-3d.batch \
+       tests/gen5-3d.batch \
+       tests/gen6-3d.batch \
+       tests/gen7-2d-copy.batch \
+       tests/gen7-3d.batch
+
+TESTS = \
+       $(BATCHES:.batch=.batch.sh)
+
+EXTRA_DIST = \
+       $(BATCHES) \
+       $(BATCHES:.batch=.batch.sh) \
+       $(BATCHES:.batch=.batch-ref.txt) \
+       $(BATCHES:.batch=.batch-ref.txt) \
+       tests/test-batch.sh
+
+test_decode_LDADD = libdrm_intel.la
+
 pkgconfig_DATA = libdrm_intel.pc
diff --git a/intel/intel_aub.h b/intel/intel_aub.h
new file mode 100644 (file)
index 0000000..a36fd53
--- /dev/null
@@ -0,0 +1,123 @@
+/*
+ * Copyright Â© 2010 Intel Corporation
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ *
+ * Authors:
+ *    Eric Anholt <eric@anholt.net>
+ *
+ */
+
+/** @file intel_aub.h
+ *
+ * The AUB file is a file format used by Intel's internal simulation
+ * and other validation tools.  It can be used at various levels by a
+ * driver to input state to the simulated hardware or a replaying
+ * debugger.
+ *
+ * We choose to dump AUB files using the trace block format for ease
+ * of implementation -- dump out the blocks of memory as plain blobs
+ * and insert ring commands to execute the batchbuffer blob.
+ */
+
+#ifndef _INTEL_AUB_H
+#define _INTEL_AUB_H
+
+#define AUB_MI_NOOP                    (0)
+#define AUB_MI_BATCH_BUFFER_START      (0x31 << 23)
+#define AUB_PIPE_CONTROL               (0x7a000002)
+
+/* DW0: instruction type. */
+
+#define CMD_AUB                        (7 << 29)
+
+#define CMD_AUB_HEADER         (CMD_AUB | (1 << 23) | (0x05 << 16))
+/* DW1 */
+# define AUB_HEADER_MAJOR_SHIFT                24
+# define AUB_HEADER_MINOR_SHIFT                16
+
+#define CMD_AUB_TRACE_HEADER_BLOCK (CMD_AUB | (1 << 23) | (0x41 << 16))
+#define CMD_AUB_DUMP_BMP           (CMD_AUB | (1 << 23) | (0x9e << 16))
+
+/* DW1 */
+#define AUB_TRACE_OPERATION_MASK       0x000000ff
+#define AUB_TRACE_OP_COMMENT           0x00000000
+#define AUB_TRACE_OP_DATA_WRITE                0x00000001
+#define AUB_TRACE_OP_COMMAND_WRITE     0x00000002
+#define AUB_TRACE_OP_MMIO_WRITE                0x00000003
+// operation = TRACE_DATA_WRITE, Type
+#define AUB_TRACE_TYPE_MASK            0x0000ff00
+#define AUB_TRACE_TYPE_NOTYPE          (0 << 8)
+#define AUB_TRACE_TYPE_BATCH           (1 << 8)
+#define AUB_TRACE_TYPE_VERTEX_BUFFER   (5 << 8)
+#define AUB_TRACE_TYPE_2D_MAP          (6 << 8)
+#define AUB_TRACE_TYPE_CUBE_MAP                (7 << 8)
+#define AUB_TRACE_TYPE_VOLUME_MAP      (9 << 8)
+#define AUB_TRACE_TYPE_1D_MAP          (10 << 8)
+#define AUB_TRACE_TYPE_CONSTANT_BUFFER (11 << 8)
+#define AUB_TRACE_TYPE_CONSTANT_URB    (12 << 8)
+#define AUB_TRACE_TYPE_INDEX_BUFFER    (13 << 8)
+#define AUB_TRACE_TYPE_GENERAL         (14 << 8)
+#define AUB_TRACE_TYPE_SURFACE         (15 << 8)
+
+
+// operation = TRACE_COMMAND_WRITE, Type =
+#define AUB_TRACE_TYPE_RING_HWB                (1 << 8)
+#define AUB_TRACE_TYPE_RING_PRB0       (2 << 8)
+#define AUB_TRACE_TYPE_RING_PRB1       (3 << 8)
+#define AUB_TRACE_TYPE_RING_PRB2       (4 << 8)
+
+// Address space
+#define AUB_TRACE_ADDRESS_SPACE_MASK   0x00ff0000
+#define AUB_TRACE_MEMTYPE_GTT          (0 << 16)
+#define AUB_TRACE_MEMTYPE_LOCAL                (1 << 16)
+#define AUB_TRACE_MEMTYPE_NONLOCAL     (2 << 16)
+#define AUB_TRACE_MEMTYPE_PCI          (3 << 16)
+#define AUB_TRACE_MEMTYPE_GTT_ENTRY     (4 << 16)
+
+/* DW2 */
+// operation = TRACE_DATA_WRITE, Type = TRACE_DATA_WRITE_GENERAL_STATE
+#define AUB_TRACE_GENERAL_STATE_MASK   0x000000ff
+
+#define AUB_TRACE_VS_STATE             0x00000001
+#define AUB_TRACE_GS_STATE             0x00000002
+#define AUB_TRACE_CL_STATE             0x00000003
+#define AUB_TRACE_SF_STATE             0x00000004
+#define AUB_TRACE_WM_STATE             0x00000005
+#define AUB_TRACE_CC_STATE             0x00000006
+#define AUB_TRACE_CL_VP                        0x00000007
+#define AUB_TRACE_SF_VP                        0x00000008
+#define AUB_TRACE_CC_VP                        0x00000009
+#define AUB_TRACE_SAMPLER_STATE                0x0000000a
+#define AUB_TRACE_KERNEL               0x0000000b
+#define AUB_TRACE_SCRATCH              0x0000000c
+#define AUB_TRACE_SDC                  0x0000000d
+#define AUB_TRACE_BLEND_STATE          0x00000016
+#define AUB_TRACE_DEPTH_STENCIL_STATE  0x00000017
+
+// operation = TRACE_DATA_WRITE, Type = TRACE_DATA_WRITE_SURFACE_STATE
+#define AUB_TRACE_SURFACE_STATE_MASK   0x00000ff00
+#define AUB_TRACE_BINDING_TABLE                0x000000100
+#define AUB_TRACE_SURFACE_STATE                0x000000200
+
+/* DW3: address */
+/* DW4: len */
+
+#endif /* _INTEL_AUB_H */
index 808e5df..c197abc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright Â© 2008 Intel Corporation
+ * Copyright Â© 2008-2012 Intel Corporation
  *
  * Permission is hereby granted, free of charge, to any person obtaining a
  * copy of this software and associated documentation files (the "Software"),
@@ -34,7 +34,9 @@
 #ifndef INTEL_BUFMGR_H
 #define INTEL_BUFMGR_H
 
+#include <stdio.h>
 #include <stdint.h>
+#include <stdio.h>
 
 struct drm_clip_rect;
 
@@ -83,6 +85,19 @@ struct _drm_intel_bo {
        int handle;
 };
 
+enum aub_dump_bmp_format {
+       AUB_DUMP_BMP_FORMAT_8BIT = 1,
+       AUB_DUMP_BMP_FORMAT_ARGB_4444 = 4,
+       AUB_DUMP_BMP_FORMAT_ARGB_0888 = 6,
+       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,
@@ -147,15 +162,28 @@ void drm_intel_bufmgr_gem_enable_reuse(drm_intel_bufmgr *bufmgr);
 void drm_intel_bufmgr_gem_enable_fenced_relocs(drm_intel_bufmgr *bufmgr);
 void drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr,
                                             int limit);
+int drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo);
 int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo);
 int drm_intel_gem_bo_unmap_gtt(drm_intel_bo *bo);
+
 int drm_intel_gem_bo_get_reloc_count(drm_intel_bo *bo);
 void drm_intel_gem_bo_clear_relocs(drm_intel_bo *bo, int start);
 void drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable);
 
+void drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable);
+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);
 
 /* drm_intel_bufmgr_fake.c */
 drm_intel_bufmgr *drm_intel_bufmgr_fake_init(int fd,
@@ -190,6 +218,19 @@ void drm_intel_bo_fake_disable_backing_store(drm_intel_bo *bo,
 void drm_intel_bufmgr_fake_contended_lock_take(drm_intel_bufmgr *bufmgr);
 void drm_intel_bufmgr_fake_evict_all(drm_intel_bufmgr *bufmgr);
 
+struct drm_intel_decode *drm_intel_decode_context_alloc(uint32_t devid);
+void drm_intel_decode_context_free(struct drm_intel_decode *ctx);
+void drm_intel_decode_set_batch_pointer(struct drm_intel_decode *ctx,
+                                       void *data, uint32_t hw_offset,
+                                       int count);
+void drm_intel_decode_set_dump_past_end(struct drm_intel_decode *ctx,
+                                       int dump_past_end);
+void drm_intel_decode_set_head_tail(struct drm_intel_decode *ctx,
+                                   uint32_t head, uint32_t tail);
+void drm_intel_decode_set_output_file(struct drm_intel_decode *ctx, FILE *out);
+void drm_intel_decode(struct drm_intel_decode *ctx);
+
+
 /** @{ Compatibility defines to keep old code building despite the symbol rename
  * from dri_* to drm_intel_*
  */
index 19441f3..b776d2f 100644 (file)
@@ -1,7 +1,7 @@
 /**************************************************************************
  *
  * Copyright Â© 2007 Red Hat Inc.
- * Copyright Â© 2007 Intel Corporation
+ * Copyright Â© 2007-2012 Intel Corporation
  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
  * All Rights Reserved.
  *
 #include "intel_bufmgr.h"
 #include "intel_bufmgr_priv.h"
 #include "intel_chipset.h"
+#include "intel_aub.h"
 #include "string.h"
 
 #include "i915_drm.h"
 
+#ifdef HAVE_VALGRIND
+#include <valgrind.h>
+#include <memcheck.h>
+#define VG(x) x
+#else
+#define VG(x)
+#endif
+
+#define VG_CLEAR(s) VG(memset(&s, 0, sizeof(s)))
+
 #define DBG(...) do {                                  \
        if (bufmgr_gem->bufmgr.debug)                   \
                fprintf(stderr, __VA_ARGS__);           \
@@ -107,8 +118,13 @@ typedef struct _drm_intel_bufmgr_gem {
        unsigned int has_bsd : 1;
        unsigned int has_blt : 1;
        unsigned int has_relaxed_fencing : 1;
+       unsigned int has_llc : 1;
        unsigned int bo_reuse : 1;
+       unsigned int no_exec : 1;
        bool fenced_relocs;
+
+       FILE *aub_file;
+       uint32_t aub_offset;
 } drm_intel_bufmgr_gem;
 
 #define DRM_INTEL_RELOC_FENCE (1<<0)
@@ -203,6 +219,11 @@ struct _drm_intel_bo_gem {
 
        /** Flags that we may need to do the SW_FINSIH ioctl on unmap. */
        bool mapped_cpu_write;
+
+       uint32_t aub_offset;
+
+       drm_intel_aub_annotation *aub_annotations;
+       unsigned aub_annotation_count;
 };
 
 static unsigned int
@@ -284,7 +305,8 @@ drm_intel_gem_bo_tile_pitch(drm_intel_bufmgr_gem *bufmgr_gem,
                return ALIGN(pitch, 64);
 
        if (*tiling_mode == I915_TILING_X
-                       || (IS_915(bufmgr_gem) && *tiling_mode == I915_TILING_Y))
+                       || (IS_915(bufmgr_gem->pci_device)
+                           && *tiling_mode == I915_TILING_Y))
                tile_width = 512;
        else
                tile_width = 128;
@@ -537,7 +559,7 @@ drm_intel_gem_bo_busy(drm_intel_bo *bo)
        struct drm_i915_gem_busy busy;
        int ret;
 
-       memset(&busy, 0, sizeof(busy));
+       VG_CLEAR(busy);
        busy.handle = bo_gem->gem_handle;
 
        ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_BUSY, &busy);
@@ -551,6 +573,7 @@ drm_intel_gem_bo_madvise_internal(drm_intel_bufmgr_gem *bufmgr_gem,
 {
        struct drm_i915_gem_madvise madv;
 
+       VG_CLEAR(madv);
        madv.handle = bo_gem->gem_handle;
        madv.madv = state;
        madv.retained = 1;
@@ -678,7 +701,8 @@ retry:
                        return NULL;
 
                bo_gem->bo.size = bo_size;
-               memset(&create, 0, sizeof(create));
+
+               VG_CLEAR(create);
                create.size = bo_size;
 
                ret = drmIoctl(bufmgr_gem->fd,
@@ -714,6 +738,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);
 
@@ -772,10 +798,11 @@ drm_intel_gem_bo_alloc_tiled(drm_intel_bufmgr *bufmgr, const char *name,
                aligned_y = y;
                height_alignment = 2;
 
-               if (IS_GEN2(bufmgr_gem) && tiling != I915_TILING_NONE)
+               if ((bufmgr_gem->gen == 2) && tiling != I915_TILING_NONE)
                        height_alignment = 16;
                else if (tiling == I915_TILING_X
-                       || (IS_915(bufmgr_gem) && tiling == I915_TILING_Y))
+                       || (IS_915(bufmgr_gem->pci_device)
+                           && tiling == I915_TILING_Y))
                        height_alignment = 8;
                else if (tiling == I915_TILING_Y)
                        height_alignment = 32;
@@ -833,7 +860,7 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
        if (!bo_gem)
                return NULL;
 
-       memset(&open_arg, 0, sizeof(open_arg));
+       VG_CLEAR(open_arg);
        open_arg.name = handle;
        ret = drmIoctl(bufmgr_gem->fd,
                       DRM_IOCTL_GEM_OPEN,
@@ -856,7 +883,7 @@ drm_intel_bo_gem_create_from_name(drm_intel_bufmgr *bufmgr,
        bo_gem->global_name = handle;
        bo_gem->reusable = false;
 
-       memset(&get_tiling, 0, sizeof(get_tiling));
+       VG_CLEAR(get_tiling);
        get_tiling.handle = bo_gem->gem_handle;
        ret = drmIoctl(bufmgr_gem->fd,
                       DRM_IOCTL_I915_GEM_GET_TILING,
@@ -887,6 +914,7 @@ drm_intel_gem_bo_free(drm_intel_bo *bo)
 
        DRMLISTDEL(&bo_gem->vma_list);
        if (bo_gem->mem_virtual) {
+               VG(VALGRIND_FREELIKE_BLOCK(bo_gem->mem_virtual, 0));
                munmap(bo_gem->mem_virtual, bo_gem->bo.size);
                bufmgr_gem->vma_count--;
        }
@@ -896,16 +924,31 @@ drm_intel_gem_bo_free(drm_intel_bo *bo)
        }
 
        /* Close this object */
-       memset(&close, 0, sizeof(close));
+       VG_CLEAR(close);
        close.handle = bo_gem->gem_handle;
        ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_CLOSE, &close);
        if (ret != 0) {
                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);
 }
 
+static void
+drm_intel_gem_bo_mark_mmaps_incoherent(drm_intel_bo *bo)
+{
+#if HAVE_VALGRIND
+       drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+       if (bo_gem->mem_virtual)
+               VALGRIND_MAKE_MEM_NOACCESS(bo_gem->mem_virtual, bo->size);
+
+       if (bo_gem->gtt_virtual)
+               VALGRIND_MAKE_MEM_NOACCESS(bo_gem->gtt_virtual, bo->size);
+#endif
+}
+
 /** Frees all cached buffers significantly older than @time. */
 static void
 drm_intel_gem_cleanup_bo_cache(drm_intel_bufmgr_gem *bufmgr_gem, time_t time)
@@ -958,7 +1001,7 @@ static void drm_intel_gem_bo_purge_vma_cache(drm_intel_bufmgr_gem *bufmgr_gem)
                                      bufmgr_gem->vma_cache.next,
                                      vma_list);
                assert(bo_gem->map_count == 0);
-               DRMLISTDEL(&bo_gem->vma_list);
+               DRMLISTDELINIT(&bo_gem->vma_list);
 
                if (bo_gem->mem_virtual) {
                        munmap(bo_gem->mem_virtual, bo_gem->bo.size);
@@ -1034,6 +1077,7 @@ drm_intel_gem_bo_unreference_final(drm_intel_bo *bo, time_t time)
                DBG("bo freed with non-zero map-count %d\n", bo_gem->map_count);
                bo_gem->map_count = 0;
                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
+               drm_intel_gem_bo_mark_mmaps_incoherent(bo);
        }
 
        DRMLISTDEL(&bo_gem->name_list);
@@ -1101,7 +1145,7 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
                DBG("bo_map: %d (%s), map_count=%d\n",
                    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
 
-               memset(&mmap_arg, 0, sizeof(mmap_arg));
+               VG_CLEAR(mmap_arg);
                mmap_arg.handle = bo_gem->gem_handle;
                mmap_arg.offset = 0;
                mmap_arg.size = bo->size;
@@ -1118,12 +1162,14 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
                        pthread_mutex_unlock(&bufmgr_gem->lock);
                        return ret;
                }
+               VG(VALGRIND_MALLOCLIKE_BLOCK(mmap_arg.addr_ptr, mmap_arg.size, 0, 1));
                bo_gem->mem_virtual = (void *)(uintptr_t) mmap_arg.addr_ptr;
        }
        DBG("bo_map: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
            bo_gem->mem_virtual);
        bo->virtual = bo_gem->mem_virtual;
 
+       VG_CLEAR(set_domain);
        set_domain.handle = bo_gem->gem_handle;
        set_domain.read_domains = I915_GEM_DOMAIN_CPU;
        if (write_enable)
@@ -1142,20 +1188,20 @@ static int drm_intel_gem_bo_map(drm_intel_bo *bo, int write_enable)
        if (write_enable)
                bo_gem->mapped_cpu_write = true;
 
+       drm_intel_gem_bo_mark_mmaps_incoherent(bo);
+       VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->mem_virtual, bo->size));
        pthread_mutex_unlock(&bufmgr_gem->lock);
 
        return 0;
 }
 
-int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
+static int
+map_gtt(drm_intel_bo *bo)
 {
        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_set_domain set_domain;
        int ret;
 
-       pthread_mutex_lock(&bufmgr_gem->lock);
-
        if (bo_gem->map_count++ == 0)
                drm_intel_gem_bo_open_vma(bufmgr_gem, bo_gem);
 
@@ -1166,7 +1212,7 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
                DBG("bo_map_gtt: mmap %d (%s), map_count=%d\n",
                    bo_gem->gem_handle, bo_gem->name, bo_gem->map_count);
 
-               memset(&mmap_arg, 0, sizeof(mmap_arg));
+               VG_CLEAR(mmap_arg);
                mmap_arg.handle = bo_gem->gem_handle;
 
                /* Get the fake offset back... */
@@ -1181,7 +1227,6 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
                            strerror(errno));
                        if (--bo_gem->map_count == 0)
                                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
-                       pthread_mutex_unlock(&bufmgr_gem->lock);
                        return ret;
                }
 
@@ -1198,7 +1243,6 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
                            strerror(errno));
                        if (--bo_gem->map_count == 0)
                                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
-                       pthread_mutex_unlock(&bufmgr_gem->lock);
                        return ret;
                }
        }
@@ -1208,7 +1252,34 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
        DBG("bo_map_gtt: %d (%s) -> %p\n", bo_gem->gem_handle, bo_gem->name,
            bo_gem->gtt_virtual);
 
-       /* Now move it to the GTT domain so that the CPU caches are flushed */
+       return 0;
+}
+
+int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
+{
+       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_set_domain set_domain;
+       int ret;
+
+       pthread_mutex_lock(&bufmgr_gem->lock);
+
+       ret = map_gtt(bo);
+       if (ret) {
+               pthread_mutex_unlock(&bufmgr_gem->lock);
+               return ret;
+       }
+
+       /* Now move it to the GTT domain so that the GPU and CPU
+        * caches are flushed and the GPU isn't actively using the
+        * buffer.
+        *
+        * The pagefault handler does this domain change for us when
+        * it has unbound the BO from the GTT, but it's up to us to
+        * tell it when we're about to use things if we had done
+        * rendering and it still happens to be bound to the GTT.
+        */
+       VG_CLEAR(set_domain);
        set_domain.handle = bo_gem->gem_handle;
        set_domain.read_domains = I915_GEM_DOMAIN_GTT;
        set_domain.write_domain = I915_GEM_DOMAIN_GTT;
@@ -1221,16 +1292,53 @@ int drm_intel_gem_bo_map_gtt(drm_intel_bo *bo)
                    strerror(errno));
        }
 
+       drm_intel_gem_bo_mark_mmaps_incoherent(bo);
+       VG(VALGRIND_MAKE_MEM_DEFINED(bo_gem->gtt_virtual, bo->size));
        pthread_mutex_unlock(&bufmgr_gem->lock);
 
        return 0;
 }
 
+/**
+ * Performs a mapping of the buffer object like the normal GTT
+ * mapping, but avoids waiting for the GPU to be done reading from or
+ * rendering to the buffer.
+ *
+ * This is used in the implementation of GL_ARB_map_buffer_range: The
+ * user asks to create a buffer, then does a mapping, fills some
+ * space, runs a drawing command, then asks to map it again without
+ * synchronizing because it guarantees that it won't write over the
+ * data that the GPU is busy using (or, more specifically, that if it
+ * does write over the data, it acknowledges that rendering is
+ * undefined).
+ */
+
+int drm_intel_gem_bo_map_unsynchronized(drm_intel_bo *bo)
+{
+       drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+       int ret;
+
+       /* If the CPU cache isn't coherent with the GTT, then use a
+        * regular synchronized mapping.  The problem is that we don't
+        * track where the buffer was last used on the CPU side in
+        * terms of drm_intel_bo_map vs drm_intel_gem_bo_map_gtt, so
+        * we would potentially corrupt the buffer even when the user
+        * does reasonable things.
+        */
+       if (!bufmgr_gem->has_llc)
+               return drm_intel_gem_bo_map_gtt(bo);
+
+       pthread_mutex_lock(&bufmgr_gem->lock);
+       ret = map_gtt(bo);
+       pthread_mutex_unlock(&bufmgr_gem->lock);
+
+       return ret;
+}
+
 static int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
 {
        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_sw_finish sw_finish;
        int ret = 0;
 
        if (bo == NULL)
@@ -1248,11 +1356,14 @@ static int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
        }
 
        if (bo_gem->mapped_cpu_write) {
+               struct drm_i915_gem_sw_finish sw_finish;
+
                /* Cause a flush to happen if the buffer's pinned for
                 * scanout, so the results show up in a timely manner.
                 * Unlike GTT set domains, this only does work if the
                 * buffer should be scanout-related.
                 */
+               VG_CLEAR(sw_finish);
                sw_finish.handle = bo_gem->gem_handle;
                ret = drmIoctl(bufmgr_gem->fd,
                               DRM_IOCTL_I915_GEM_SW_FINISH,
@@ -1268,6 +1379,7 @@ static int drm_intel_gem_bo_unmap(drm_intel_bo *bo)
         */
        if (--bo_gem->map_count == 0) {
                drm_intel_gem_bo_close_vma(bufmgr_gem, bo_gem);
+               drm_intel_gem_bo_mark_mmaps_incoherent(bo);
                bo->virtual = NULL;
        }
        pthread_mutex_unlock(&bufmgr_gem->lock);
@@ -1289,7 +1401,7 @@ drm_intel_gem_bo_subdata(drm_intel_bo *bo, unsigned long offset,
        struct drm_i915_gem_pwrite pwrite;
        int ret;
 
-       memset(&pwrite, 0, sizeof(pwrite));
+       VG_CLEAR(pwrite);
        pwrite.handle = bo_gem->gem_handle;
        pwrite.offset = offset;
        pwrite.size = size;
@@ -1314,6 +1426,7 @@ drm_intel_gem_get_pipe_from_crtc_id(drm_intel_bufmgr *bufmgr, int crtc_id)
        struct drm_i915_get_pipe_from_crtc_id get_pipe_from_crtc_id;
        int ret;
 
+       VG_CLEAR(get_pipe_from_crtc_id);
        get_pipe_from_crtc_id.crtc_id = crtc_id;
        ret = drmIoctl(bufmgr_gem->fd,
                       DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID,
@@ -1340,7 +1453,7 @@ drm_intel_gem_bo_get_subdata(drm_intel_bo *bo, unsigned long offset,
        struct drm_i915_gem_pread pread;
        int ret;
 
-       memset(&pread, 0, sizeof(pread));
+       VG_CLEAR(pread);
        pread.handle = bo_gem->gem_handle;
        pread.offset = offset;
        pread.size = size;
@@ -1380,6 +1493,7 @@ drm_intel_gem_bo_start_gtt_access(drm_intel_bo *bo, int write_enable)
        struct drm_i915_gem_set_domain set_domain;
        int ret;
 
+       VG_CLEAR(set_domain);
        set_domain.handle = bo_gem->gem_handle;
        set_domain.read_domains = I915_GEM_DOMAIN_GTT;
        set_domain.write_domain = write_enable ? I915_GEM_DOMAIN_GTT : 0;
@@ -1592,6 +1706,8 @@ drm_intel_gem_bo_process_reloc(drm_intel_bo *bo)
                if (target_bo == bo)
                        continue;
 
+               drm_intel_gem_bo_mark_mmaps_incoherent(bo);
+
                /* Continue walking the tree depth-first. */
                drm_intel_gem_bo_process_reloc(target_bo);
 
@@ -1616,6 +1732,8 @@ drm_intel_gem_bo_process_reloc2(drm_intel_bo *bo)
                if (target_bo == bo)
                        continue;
 
+               drm_intel_gem_bo_mark_mmaps_incoherent(bo);
+
                /* Continue walking the tree depth-first. */
                drm_intel_gem_bo_process_reloc2(target_bo);
 
@@ -1667,6 +1785,287 @@ drm_intel_update_buffer_offsets2 (drm_intel_bufmgr_gem *bufmgr_gem)
        }
 }
 
+static void
+aub_out(drm_intel_bufmgr_gem *bufmgr_gem, uint32_t data)
+{
+       fwrite(&data, 1, 4, bufmgr_gem->aub_file);
+}
+
+static void
+aub_out_data(drm_intel_bufmgr_gem *bufmgr_gem, void *data, size_t size)
+{
+       fwrite(data, 1, size, bufmgr_gem->aub_file);
+}
+
+static void
+aub_write_bo_data(drm_intel_bo *bo, uint32_t offset, uint32_t size)
+{
+       drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+       drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+       uint32_t *data;
+       unsigned int i;
+
+       data = malloc(bo->size);
+       drm_intel_bo_get_subdata(bo, offset, size, data);
+
+       /* Easy mode: write out bo with no relocations */
+       if (!bo_gem->reloc_count) {
+               aub_out_data(bufmgr_gem, data, size);
+               free(data);
+               return;
+       }
+
+       /* Otherwise, handle the relocations while writing. */
+       for (i = 0; i < size / 4; i++) {
+               int r;
+               for (r = 0; r < bo_gem->reloc_count; r++) {
+                       struct drm_i915_gem_relocation_entry *reloc;
+                       drm_intel_reloc_target *info;
+
+                       reloc = &bo_gem->relocs[r];
+                       info = &bo_gem->reloc_target_info[r];
+
+                       if (reloc->offset == offset + i * 4) {
+                               drm_intel_bo_gem *target_gem;
+                               uint32_t val;
+
+                               target_gem = (drm_intel_bo_gem *)info->bo;
+
+                               val = reloc->delta;
+                               val += target_gem->aub_offset;
+
+                               aub_out(bufmgr_gem, val);
+                               data[i] = val;
+                               break;
+                       }
+               }
+               if (r == bo_gem->reloc_count) {
+                       /* no relocation, just the data */
+                       aub_out(bufmgr_gem, data[i]);
+               }
+       }
+
+       free(data);
+}
+
+static void
+aub_bo_get_address(drm_intel_bo *bo)
+{
+       drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+       drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+       /* Give the object a graphics address in the AUB file.  We
+        * don't just use the GEM object address because we do AUB
+        * dumping before execution -- we want to successfully log
+        * when the hardware might hang, and we might even want to aub
+        * capture for a driver trying to execute on a different
+        * generation of hardware by disabling the actual kernel exec
+        * call.
+        */
+       bo_gem->aub_offset = bufmgr_gem->aub_offset;
+       bufmgr_gem->aub_offset += bo->size;
+       /* XXX: Handle aperture overflow. */
+       assert(bufmgr_gem->aub_offset < 256 * 1024 * 1024);
+}
+
+static void
+aub_write_trace_block(drm_intel_bo *bo, uint32_t type, uint32_t subtype,
+                     uint32_t offset, uint32_t size)
+{
+       drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+       drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *) bo;
+
+       aub_out(bufmgr_gem,
+               CMD_AUB_TRACE_HEADER_BLOCK |
+               (5 - 2));
+       aub_out(bufmgr_gem,
+               AUB_TRACE_MEMTYPE_GTT | type | AUB_TRACE_OP_DATA_WRITE);
+       aub_out(bufmgr_gem, subtype);
+       aub_out(bufmgr_gem, bo_gem->aub_offset + offset);
+       aub_out(bufmgr_gem, size);
+       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_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 sub_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, 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);
+       }
+}
+
+/*
+ * Make a ringbuffer on fly and dump it
+ */
+static void
+aub_build_dump_ringbuffer(drm_intel_bufmgr_gem *bufmgr_gem,
+                         uint32_t batch_buffer, int ring_flag)
+{
+       uint32_t ringbuffer[4096];
+       int ring = AUB_TRACE_TYPE_RING_PRB0; /* The default ring */
+       int ring_count = 0;
+
+       if (ring_flag == I915_EXEC_BSD)
+               ring = AUB_TRACE_TYPE_RING_PRB1;
+
+       /* Make a ring buffer to execute our batchbuffer. */
+       memset(ringbuffer, 0, sizeof(ringbuffer));
+       ringbuffer[ring_count++] = AUB_MI_BATCH_BUFFER_START;
+       ringbuffer[ring_count++] = batch_buffer;
+
+       /* Write out the ring.  This appears to trigger execution of
+        * the ring in the simulator.
+        */
+       aub_out(bufmgr_gem,
+               CMD_AUB_TRACE_HEADER_BLOCK |
+               (5 - 2));
+       aub_out(bufmgr_gem,
+               AUB_TRACE_MEMTYPE_GTT | ring | AUB_TRACE_OP_COMMAND_WRITE);
+       aub_out(bufmgr_gem, 0); /* general/surface subtype */
+       aub_out(bufmgr_gem, bufmgr_gem->aub_offset);
+       aub_out(bufmgr_gem, ring_count * 4);
+
+       /* FIXME: Need some flush operations here? */
+       aub_out_data(bufmgr_gem, ringbuffer, ring_count * 4);
+
+       /* Update offset pointer */
+       bufmgr_gem->aub_offset += 4096;
+}
+
+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)
+{
+       drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *) bo->bufmgr;
+       drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
+       uint32_t cpp;
+
+       switch (format) {
+       case AUB_DUMP_BMP_FORMAT_8BIT:
+               cpp = 1;
+               break;
+       case AUB_DUMP_BMP_FORMAT_ARGB_4444:
+               cpp = 2;
+               break;
+       case AUB_DUMP_BMP_FORMAT_ARGB_0888:
+       case AUB_DUMP_BMP_FORMAT_ARGB_8888:
+               cpp = 4;
+               break;
+       default:
+               printf("Unknown AUB dump format %d\n", format);
+               return;
+       }
+
+       if (!bufmgr_gem->aub_file)
+               return;
+
+       aub_out(bufmgr_gem, CMD_AUB_DUMP_BMP | 4);
+       aub_out(bufmgr_gem, (y1 << 16) | x1);
+       aub_out(bufmgr_gem,
+               (format << 24) |
+               (cpp << 19) |
+               pitch / 4);
+       aub_out(bufmgr_gem, (height << 16) | width);
+       aub_out(bufmgr_gem, bo_gem->aub_offset + offset);
+       aub_out(bufmgr_gem,
+               ((bo_gem->tiling_mode != I915_TILING_NONE) ? (1 << 2) : 0) |
+               ((bo_gem->tiling_mode == I915_TILING_Y) ? (1 << 3) : 0));
+}
+
+static void
+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;
+
+       /* 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);
+       }
+
+       /* Write out all buffers to AUB memory */
+       for (i = 0; i < bufmgr_gem->exec_count; i++) {
+               aub_write_bo(bufmgr_gem->exec_bos[i]);
+       }
+
+       /* 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);
+
+       fflush(bufmgr_gem->aub_file);
+
+       /*
+        * One frame has been dumped. So reset the aub_offset for the next frame.
+        *
+        * FIXME: Can we do this?
+        */
+       bufmgr_gem->aub_offset = 0x10000;
+}
+
 static int
 drm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
                      drm_clip_rect_t * cliprects, int num_cliprects, int DR4)
@@ -1688,6 +2087,7 @@ drm_intel_gem_bo_exec(drm_intel_bo *bo, int used,
         */
        drm_intel_add_validate_buffer(bo);
 
+       VG_CLEAR(execbuf);
        execbuf.buffers_ptr = (uintptr_t) bufmgr_gem->exec_objects;
        execbuf.buffer_count = bufmgr_gem->exec_count;
        execbuf.batch_start_offset = 0;
@@ -1740,7 +2140,8 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
 {
        drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bo->bufmgr;
        struct drm_i915_gem_execbuffer2 execbuf;
-       int ret, i;
+       int ret = 0;
+       int i;
 
        switch (flags & 0x7) {
        default:
@@ -1767,6 +2168,7 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
         */
        drm_intel_add_validate_buffer2(bo, 0);
 
+       VG_CLEAR(execbuf);
        execbuf.buffers_ptr = (uintptr_t)bufmgr_gem->exec2_objects;
        execbuf.buffer_count = bufmgr_gem->exec_count;
        execbuf.batch_start_offset = 0;
@@ -1779,6 +2181,11 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
        execbuf.rsvd1 = 0;
        execbuf.rsvd2 = 0;
 
+       aub_exec(bo, flags, used);
+
+       if (bufmgr_gem->no_exec)
+               goto skip_execution;
+
        ret = drmIoctl(bufmgr_gem->fd,
                       DRM_IOCTL_I915_GEM_EXECBUFFER2,
                       &execbuf);
@@ -1796,6 +2203,7 @@ drm_intel_gem_bo_mrb_exec2(drm_intel_bo *bo, int used,
        }
        drm_intel_update_buffer_offsets2(bufmgr_gem);
 
+skip_execution:
        if (bufmgr_gem->bufmgr.debug)
                drm_intel_gem_dump_validation_list(bufmgr_gem);
 
@@ -1831,7 +2239,7 @@ drm_intel_gem_bo_pin(drm_intel_bo *bo, uint32_t alignment)
        struct drm_i915_gem_pin pin;
        int ret;
 
-       memset(&pin, 0, sizeof(pin));
+       VG_CLEAR(pin);
        pin.handle = bo_gem->gem_handle;
        pin.alignment = alignment;
 
@@ -1853,7 +2261,7 @@ drm_intel_gem_bo_unpin(drm_intel_bo *bo)
        struct drm_i915_gem_unpin unpin;
        int ret;
 
-       memset(&unpin, 0, sizeof(unpin));
+       VG_CLEAR(unpin);
        unpin.handle = bo_gem->gem_handle;
 
        ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_UNPIN, &unpin);
@@ -1939,16 +2347,18 @@ drm_intel_gem_bo_flink(drm_intel_bo *bo, uint32_t * name)
 {
        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_gem_flink flink;
        int ret;
 
        if (!bo_gem->global_name) {
-               memset(&flink, 0, sizeof(flink));
+               struct drm_gem_flink flink;
+
+               VG_CLEAR(flink);
                flink.handle = bo_gem->gem_handle;
 
                ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_GEM_FLINK, &flink);
                if (ret != 0)
                        return -errno;
+
                bo_gem->global_name = flink.name;
                bo_gem->reusable = false;
 
@@ -2264,6 +2674,143 @@ drm_intel_bufmgr_gem_set_vma_cache_size(drm_intel_bufmgr *bufmgr, int limit)
 }
 
 /**
+ * Get the PCI ID for the device.  This can be overridden by setting the
+ * INTEL_DEVID_OVERRIDE environment variable to the desired ID.
+ */
+static int
+get_pci_device_id(drm_intel_bufmgr_gem *bufmgr_gem)
+{
+       char *devid_override;
+       int devid;
+       int ret;
+       drm_i915_getparam_t gp;
+
+       if (geteuid() == getuid()) {
+               devid_override = getenv("INTEL_DEVID_OVERRIDE");
+               if (devid_override) {
+                       bufmgr_gem->no_exec = true;
+                       return strtod(devid_override, NULL);
+               }
+       }
+
+       VG_CLEAR(devid);
+       VG_CLEAR(gp);
+       gp.param = I915_PARAM_CHIPSET_ID;
+       gp.value = &devid;
+       ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+       if (ret) {
+               fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno);
+               fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value);
+       }
+       return devid;
+}
+
+int
+drm_intel_bufmgr_gem_get_devid(drm_intel_bufmgr *bufmgr)
+{
+       drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
+
+       return bufmgr_gem->pci_device;
+}
+
+/**
+ * Sets up AUB dumping.
+ *
+ * This is a trace file format that can be used with the simulator.
+ * Packets are emitted in a format somewhat like GPU command packets.
+ * You can set up a GTT and upload your objects into the referenced
+ * space, then send off batchbuffers and get BMPs out the other end.
+ */
+void
+drm_intel_bufmgr_gem_set_aub_dump(drm_intel_bufmgr *bufmgr, int enable)
+{
+       drm_intel_bufmgr_gem *bufmgr_gem = (drm_intel_bufmgr_gem *)bufmgr;
+       int entry = 0x200003;
+       int i;
+       int gtt_size = 0x10000;
+
+       if (!enable) {
+               if (bufmgr_gem->aub_file) {
+                       fclose(bufmgr_gem->aub_file);
+                       bufmgr_gem->aub_file = NULL;
+               }
+       }
+
+       if (geteuid() != getuid())
+               return;
+
+       bufmgr_gem->aub_file = fopen("intel.aub", "w+");
+       if (!bufmgr_gem->aub_file)
+               return;
+
+       /* Start allocating objects from just after the GTT. */
+       bufmgr_gem->aub_offset = gtt_size;
+
+       /* Start with a (required) version packet. */
+       aub_out(bufmgr_gem, CMD_AUB_HEADER | (13 - 2));
+       aub_out(bufmgr_gem,
+               (4 << AUB_HEADER_MAJOR_SHIFT) |
+               (0 << AUB_HEADER_MINOR_SHIFT));
+       for (i = 0; i < 8; i++) {
+               aub_out(bufmgr_gem, 0); /* app name */
+       }
+       aub_out(bufmgr_gem, 0); /* timestamp */
+       aub_out(bufmgr_gem, 0); /* timestamp */
+       aub_out(bufmgr_gem, 0); /* comment len */
+
+       /* Set up the GTT. The max we can handle is 256M */
+       aub_out(bufmgr_gem, CMD_AUB_TRACE_HEADER_BLOCK | (5 - 2));
+       aub_out(bufmgr_gem, AUB_TRACE_MEMTYPE_NONLOCAL | 0 | AUB_TRACE_OP_DATA_WRITE);
+       aub_out(bufmgr_gem, 0); /* subtype */
+       aub_out(bufmgr_gem, 0); /* offset */
+       aub_out(bufmgr_gem, gtt_size); /* size */
+       for (i = 0x000; i < gtt_size; i += 4, entry += 0x1000) {
+               aub_out(bufmgr_gem, entry);
+       }
+}
+
+/**
+ * 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.
  *
@@ -2305,24 +2852,25 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
                        (int)bufmgr_gem->gtt_size / 1024);
        }
 
-       gp.param = I915_PARAM_CHIPSET_ID;
-       gp.value = &bufmgr_gem->pci_device;
-       ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
-       if (ret) {
-               fprintf(stderr, "get chip id failed: %d [%d]\n", ret, errno);
-               fprintf(stderr, "param: %d, val: %d\n", gp.param, *gp.value);
-       }
+       bufmgr_gem->pci_device = get_pci_device_id(bufmgr_gem);
 
-       if (IS_GEN2(bufmgr_gem))
+       if (IS_GEN2(bufmgr_gem->pci_device))
                bufmgr_gem->gen = 2;
-       else if (IS_GEN3(bufmgr_gem))
+       else if (IS_GEN3(bufmgr_gem->pci_device))
                bufmgr_gem->gen = 3;
-       else if (IS_GEN4(bufmgr_gem))
+       else if (IS_GEN4(bufmgr_gem->pci_device))
                bufmgr_gem->gen = 4;
-       else
+       else if (IS_GEN5(bufmgr_gem->pci_device))
+               bufmgr_gem->gen = 5;
+       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);
 
-       if (IS_GEN3(bufmgr_gem) && bufmgr_gem->gtt_size > 256*1024*1024) {
+       if (IS_GEN3(bufmgr_gem->pci_device) &&
+           bufmgr_gem->gtt_size > 256*1024*1024) {
                /* The unmappable part of gtt on gen 3 (i.e. above 256MB) can't
                 * be used for tiled blits. To simplify the accounting, just
                 * substract the unmappable part (fixed to 256MB on all known
@@ -2330,6 +2878,7 @@ drm_intel_bufmgr_gem_init(int fd, int batch_size)
                bufmgr_gem->gtt_size -= 256*1024*1024;
        }
 
+       VG_CLEAR(gp);
        gp.value = &tmp;
 
        gp.param = I915_PARAM_HAS_EXECBUF2;
@@ -2349,6 +2898,17 @@ 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_LLC;
+       ret = drmIoctl(bufmgr_gem->fd, DRM_IOCTL_I915_GETPARAM, &gp);
+       if (ret != 0) {
+               /* Kernel does not supports HAS_LLC query, fallback to GPU
+                * generation detection and assume that we have LLC on GEN6/7
+                */
+               bufmgr_gem->has_llc = (IS_GEN6(bufmgr_gem->pci_device) |
+                               IS_GEN7(bufmgr_gem->pci_device));
+       } else
+               bufmgr_gem->has_llc = ret == 0;
+
        if (bufmgr_gem->gen < 4) {
                gp.param = I915_PARAM_NUM_FENCES_AVAIL;
                gp.value = &bufmgr_gem->available_fences;
index b4e0747..9c1abc8 100644 (file)
 #ifndef _INTEL_CHIPSET_H
 #define _INTEL_CHIPSET_H
 
-#define IS_830(dev) ((dev)->pci_device == 0x3577)
-#define IS_845(dev) ((dev)->pci_device == 0x2562)
-#define IS_85X(dev) ((dev)->pci_device == 0x3582)
-#define IS_865(dev) ((dev)->pci_device == 0x2572)
+#define PCI_CHIP_ILD_G                  0x0042
+#define PCI_CHIP_ILM_G                  0x0046
+
+#define PCI_CHIP_SANDYBRIDGE_GT1       0x0102 /* desktop */
+#define PCI_CHIP_SANDYBRIDGE_GT2       0x0112
+#define PCI_CHIP_SANDYBRIDGE_GT2_PLUS  0x0122
+#define PCI_CHIP_SANDYBRIDGE_M_GT1     0x0106 /* mobile */
+#define PCI_CHIP_SANDYBRIDGE_M_GT2     0x0116
+#define PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS        0x0126
+#define PCI_CHIP_SANDYBRIDGE_S         0x010A /* server */
+
+#define PCI_CHIP_IVYBRIDGE_GT1         0x0152 /* desktop */
+#define PCI_CHIP_IVYBRIDGE_GT2         0x0162
+#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_M_GT1          0x0406 /* Mobile */
+#define PCI_CHIP_HASWELL_M_GT2          0x0416
+#define PCI_CHIP_HASWELL_M_ULT_GT2      0x0A16 /* Mobile ULT */
+
+#define IS_830(dev) (dev == 0x3577)
+#define IS_845(dev) (dev == 0x2562)
+#define IS_85X(dev) (dev == 0x3582)
+#define IS_865(dev) (dev == 0x2572)
 
 #define IS_GEN2(dev) (IS_830(dev) ||                           \
                      IS_845(dev) ||                            \
                      IS_85X(dev) ||                            \
                      IS_865(dev))
 
-#define IS_915G(dev) ((dev)->pci_device == 0x2582 ||           \
-                      (dev)->pci_device == 0x258a)
-#define IS_915GM(dev) ((dev)->pci_device == 0x2592)
-#define IS_945G(dev) ((dev)->pci_device == 0x2772)
-#define IS_945GM(dev) ((dev)->pci_device == 0x27A2 ||          \
-                        (dev)->pci_device == 0x27AE)
+#define IS_915G(dev) (dev == 0x2582 ||         \
+                      dev == 0x258a)
+#define IS_915GM(dev) (dev == 0x2592)
+#define IS_945G(dev) (dev == 0x2772)
+#define IS_945GM(dev) (dev == 0x27A2 ||                \
+                        dev == 0x27AE)
 
 #define IS_915(dev) (IS_915G(dev) ||                           \
                     IS_915GM(dev))
                     IS_G33(dev) ||                             \
                     IS_PINEVIEW(dev))
 
-#define IS_G33(dev)    ((dev)->pci_device == 0x29C2 ||         \
-                        (dev)->pci_device == 0x29B2 ||         \
-                        (dev)->pci_device == 0x29D2)
+#define IS_G33(dev)    (dev == 0x29C2 ||               \
+                        dev == 0x29B2 ||               \
+                        dev == 0x29D2)
 
-#define IS_PINEVIEW(dev) ((dev)->pci_device == 0xa001 ||       \
-                         (dev)->pci_device == 0xa011)
+#define IS_PINEVIEW(dev) (dev == 0xa001 ||     \
+                         dev == 0xa011)
 
 #define IS_GEN3(dev) (IS_915(dev) ||                           \
                      IS_945(dev) ||                            \
                      IS_G33(dev) ||                            \
                      IS_PINEVIEW(dev))
 
-#define IS_I965GM(dev) ((dev)->pci_device == 0x2A02)
-
-#define IS_GEN4(dev) ((dev)->pci_device == 0x2972 ||   \
-                     (dev)->pci_device == 0x2982 ||    \
-                     (dev)->pci_device == 0x2992 ||    \
-                     (dev)->pci_device == 0x29A2 ||    \
-                     (dev)->pci_device == 0x2A02 ||    \
-                     (dev)->pci_device == 0x2A12 ||    \
-                     (dev)->pci_device == 0x2A42 ||    \
-                     (dev)->pci_device == 0x2E02 ||    \
-                     (dev)->pci_device == 0x2E12 ||    \
-                     (dev)->pci_device == 0x2E22 ||    \
-                     (dev)->pci_device == 0x2E32 ||    \
-                     (dev)->pci_device == 0x2E42 ||    \
-                     (dev)->pci_device == 0x0042 ||    \
-                     (dev)->pci_device == 0x0046 ||    \
+#define IS_I965GM(dev) (dev == 0x2A02)
+
+#define IS_GEN4(dev) (dev == 0x2972 || \
+                     dev == 0x2982 ||  \
+                     dev == 0x2992 ||  \
+                     dev == 0x29A2 ||  \
+                     dev == 0x2A02 ||  \
+                     dev == 0x2A12 ||  \
+                     dev == 0x2A42 ||  \
+                     dev == 0x2E02 ||  \
+                     dev == 0x2E12 ||  \
+                     dev == 0x2E22 ||  \
+                     dev == 0x2E32 ||  \
+                     dev == 0x2E42 ||  \
+                     dev == 0x0042 ||  \
+                     dev == 0x0046 ||  \
                      IS_I965GM(dev) || \
                      IS_G4X(dev))
 
-#define IS_GM45(dev) ((dev)->pci_device == 0x2A42)
+#define IS_GM45(dev) (dev == 0x2A42)
+
+
+#define IS_GEN5(dev)   (dev == PCI_CHIP_ILD_G || \
+                        dev == PCI_CHIP_ILM_G)
+
+#define IS_GEN6(dev)   (dev == PCI_CHIP_SANDYBRIDGE_GT1 || \
+                        dev == PCI_CHIP_SANDYBRIDGE_GT2 || \
+                        dev == PCI_CHIP_SANDYBRIDGE_GT2_PLUS || \
+                        dev == PCI_CHIP_SANDYBRIDGE_M_GT1 || \
+                        dev == PCI_CHIP_SANDYBRIDGE_M_GT2 || \
+                        dev == PCI_CHIP_SANDYBRIDGE_M_GT2_PLUS || \
+                        dev == PCI_CHIP_SANDYBRIDGE_S)
+
+#define IS_GEN7(devid)          (IS_IVYBRIDGE(devid) || \
+                                 IS_HASWELL(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_GT2)
+
+#define IS_HSW_GT1(devid)       (devid == PCI_CHIP_HASWELL_GT1 || \
+                                 devid == PCI_CHIP_HASWELL_M_GT1)
+#define IS_HSW_GT2(devid)       (devid == PCI_CHIP_HASWELL_GT2 || \
+                                 devid == PCI_CHIP_HASWELL_M_GT2 || \
+                                 devid == PCI_CHIP_HASWELL_M_ULT_GT2)
+
+#define IS_HASWELL(devid)       (IS_HSW_GT1(devid) || \
+                                 IS_HSW_GT2(devid))
 
-#define IS_G4X(dev) ((dev)->pci_device == 0x2E02 || \
-                     (dev)->pci_device == 0x2E12 || \
-                     (dev)->pci_device == 0x2E22 || \
-                     (dev)->pci_device == 0x2E32 || \
-                     (dev)->pci_device == 0x2E42 || \
+#define IS_G4X(dev) (dev == 0x2E02 || \
+                     dev == 0x2E12 || \
+                     dev == 0x2E22 || \
+                     dev == 0x2E32 || \
+                     dev == 0x2E42 || \
                     IS_GM45(dev))
 
 #define IS_9XX(dev) (IS_GEN3(dev) ||                           \
                     IS_GEN4(dev) ||                            \
                     IS_GEN5(dev) ||                            \
-                    IS_GEN6(dev))
+                    IS_GEN6(dev) ||                            \
+                    IS_GEN7(dev))
 
 #endif /* _INTEL_CHIPSET_H */
diff --git a/intel/intel_decode.c b/intel/intel_decode.c
new file mode 100644 (file)
index 0000000..bf23706
--- /dev/null
@@ -0,0 +1,3956 @@
+/*
+ * Copyright Â© 2009-2011 Intel Corporation
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <assert.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "intel_chipset.h"
+#include "intel_bufmgr.h"
+
+/* Struct for tracking drm_intel_decode state. */
+struct drm_intel_decode {
+       /** stdio file where the output should land.  Defaults to stdout. */
+       FILE *out;
+
+       /** PCI device ID. */
+       uint32_t devid;
+
+       /**
+        * Shorthand device identifier: 3 is 915, 4 is 965, 5 is
+        * Ironlake, etc.
+        */
+       int gen;
+
+       /** GPU address of the start of the current packet. */
+       uint32_t hw_offset;
+       /** CPU virtual address of the start of the current packet. */
+       uint32_t *data;
+       /** DWORDs of remaining batchbuffer data starting from the packet. */
+       uint32_t count;
+
+       /** GPU address of the start of the batchbuffer data. */
+       uint32_t base_hw_offset;
+       /** CPU Virtual address of the start of the batchbuffer data. */
+       uint32_t *base_data;
+       /** Number of DWORDs of batchbuffer data. */
+       uint32_t base_count;
+
+       /** @{
+        * GPU head and tail pointers, which will be noted in the dump, or ~0.
+        */
+       uint32_t head, tail;
+       /** @} */
+
+       /**
+        * Whether to dump the dwords after MI_BATCHBUFFER_END.
+        *
+        * This sometimes provides clues in corrupted batchbuffers,
+        * and is used by the intel-gpu-tools.
+        */
+       bool dump_past_end;
+
+       bool overflowed;
+};
+
+static FILE *out;
+static uint32_t saved_s2 = 0, saved_s4 = 0;
+static char saved_s2_set = 0, saved_s4_set = 0;
+static uint32_t head_offset = 0xffffffff;      /* undefined */
+static uint32_t tail_offset = 0xffffffff;      /* undefined */
+
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(A) (sizeof(A)/sizeof(A[0]))
+#endif
+
+#define BUFFER_FAIL(_count, _len, _name) do {                  \
+    fprintf(out, "Buffer size too small in %s (%d < %d)\n",    \
+           (_name), (_count), (_len));                         \
+    return _count;                                             \
+} while (0)
+
+static float int_as_float(uint32_t intval)
+{
+       union intfloat {
+               uint32_t i;
+               float f;
+       } uval;
+
+       uval.i = intval;
+       return uval.f;
+}
+
+static void
+instr_out(struct drm_intel_decode *ctx, unsigned int index,
+         const char *fmt, ...) __attribute__((format(__printf__, 3, 4)));
+
+static void
+instr_out(struct drm_intel_decode *ctx, unsigned int index,
+         const char *fmt, ...)
+{
+       va_list va;
+       const char *parseinfo;
+       uint32_t offset = ctx->hw_offset + index * 4;
+
+       if (index > ctx->count) {
+               if (!ctx->overflowed) {
+                       fprintf(out, "ERROR: Decode attempted to continue beyond end of batchbuffer\n");
+                       ctx->overflowed = true;
+               }
+               return;
+       }
+
+       if (offset == head_offset)
+               parseinfo = "HEAD";
+       else if (offset == tail_offset)
+               parseinfo = "TAIL";
+       else
+               parseinfo = "    ";
+
+       fprintf(out, "0x%08x: %s 0x%08x: %s", offset, parseinfo,
+               ctx->data[index], index == 0 ? "" : "   ");
+       va_start(va, fmt);
+       vfprintf(out, fmt, va);
+       va_end(va);
+}
+
+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;
+       const char *post_sync_op = "";
+       uint32_t *data = ctx->data;
+
+       struct {
+               uint32_t opcode;
+               int len_mask;
+               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" },
+               { 0x30, 0x3f, 3, 3, "MI_BATCH_BUFFER" },
+               { 0x31, 0x3f, 2, 2, "MI_BATCH_BUFFER_START" },
+               { 0x14, 0x3f, 3, 3, "MI_DISPLAY_BUFFER_INFO" },
+               { 0x04, 0, 1, 1, "MI_FLUSH" },
+               { 0x22, 0x1f, 3, 3, "MI_LOAD_REGISTER_IMM" },
+               { 0x13, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_EXCL" },
+               { 0x12, 0x3f, 2, 2, "MI_LOAD_SCAN_LINES_INCL" },
+               { 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" },
+               { 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", 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]);
+            opcode++) {
+               if ((data[0] & 0x1f800000) >> 23 == opcodes_mi[opcode].opcode) {
+                       len = 1;
+                       if (opcodes_mi[opcode].max_len > 1) {
+                               len =
+                                   (data[0] & opcodes_mi[opcode].len_mask) + 2;
+                               if (len < opcodes_mi[opcode].min_len
+                                   || len > opcodes_mi[opcode].max_len) {
+                                       fprintf(out,
+                                               "Bad length (%d) in %s, [%d, %d]\n",
+                                               len, opcodes_mi[opcode].name,
+                                               opcodes_mi[opcode].min_len,
+                                               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");
+               return -1;
+       case 0x16:
+               instr_out(ctx, 0, "MI_SEMAPHORE_MBOX%s%s%s%s %u\n",
+                         data[0] & (1 << 22) ? " global gtt," : "",
+                         data[0] & (1 << 21) ? " update semaphore," : "",
+                         data[0] & (1 << 20) ? " compare semaphore," : "",
+                         data[0] & (1 << 18) ? " use compare reg" : "",
+                         (data[0] & (0x3 << 16)) >> 16);
+               instr_out(ctx, 1, "value\n");
+               instr_out(ctx, 2, "address\n");
+               return len;
+       case 0x21:
+               instr_out(ctx, 0, "MI_STORE_DATA_INDEX%s\n",
+                         data[0] & (1 << 21) ? " use per-process HWS," : "");
+               instr_out(ctx, 1, "index\n");
+               instr_out(ctx, 2, "dword\n");
+               if (len == 4)
+                       instr_out(ctx, 3, "upper dword\n");
+               return len;
+       case 0x00:
+               if (data[0] & (1 << 22))
+                       instr_out(ctx, 0,
+                                 "MI_NOOP write NOPID reg, val=0x%x\n",
+                                 data[0] & ((1 << 22) - 1));
+               else
+                       instr_out(ctx, 0, "MI_NOOP\n");
+               return len;
+       case 0x26:
+               switch (data[0] & (0x3 << 14)) {
+               case (0 << 14):
+                       post_sync_op = "no write";
+                       break;
+               case (1 << 14):
+                       post_sync_op = "write data";
+                       break;
+               case (2 << 14):
+                       post_sync_op = "reserved";
+                       break;
+               case (3 << 14):
+                       post_sync_op = "write TIMESTAMP";
+                       break;
+               }
+               instr_out(ctx, 0,
+                         "MI_FLUSH_DW%s%s%s%s post_sync_op='%s' %s%s\n",
+                         data[0] & (1 << 22) ?
+                         " enable protected mem (BCS-only)," : "",
+                         data[0] & (1 << 21) ? " store in hws," : "",
+                         data[0] & (1 << 18) ? " invalidate tlb," : "",
+                         data[0] & (1 << 17) ? " flush gfdt," : "",
+                         post_sync_op,
+                         data[0] & (1 << 8) ? " enable notify interrupt," : "",
+                         data[0] & (1 << 7) ?
+                         " invalidate video state (BCS-only)," : "");
+               if (data[0] & (1 << 21))
+                       instr_out(ctx, 1, "hws index\n");
+               else
+                       instr_out(ctx, 1, "address\n");
+               instr_out(ctx, 2, "dword\n");
+               if (len == 4)
+                       instr_out(ctx, 3, "upper dword\n");
+               return len;
+       }
+
+       for (opcode = 0; opcode < sizeof(opcodes_mi) / sizeof(opcodes_mi[0]);
+            opcode++) {
+               if ((data[0] & 0x1f800000) >> 23 == opcodes_mi[opcode].opcode) {
+                       unsigned int i;
+
+                       instr_out(ctx, 0, "%s\n",
+                                 opcodes_mi[opcode].name);
+                       for (i = 1; i < len; i++) {
+                               instr_out(ctx, i, "dword %d\n", i);
+                       }
+
+                       return len;
+               }
+       }
+
+       instr_out(ctx, 0, "MI UNKNOWN\n");
+       return 1;
+}
+
+static void
+decode_2d_br00(struct drm_intel_decode *ctx, const char *cmd)
+{
+       instr_out(ctx, 0,
+                 "%s (rgb %sabled, alpha %sabled, src tile %d, dst tile %d)\n",
+                 cmd,
+                 (ctx->data[0] & (1 << 20)) ? "en" : "dis",
+                 (ctx->data[0] & (1 << 21)) ? "en" : "dis",
+                 (ctx->data[0] >> 15) & 1,
+                 (ctx->data[0] >> 11) & 1);
+}
+
+static void
+decode_2d_br01(struct drm_intel_decode *ctx)
+{
+       const char *format;
+       switch ((ctx->data[1] >> 24) & 0x3) {
+       case 0:
+               format = "8";
+               break;
+       case 1:
+               format = "565";
+               break;
+       case 2:
+               format = "1555";
+               break;
+       case 3:
+               format = "8888";
+               break;
+       }
+
+       instr_out(ctx, 1,
+                 "format %s, pitch %d, rop 0x%02x, "
+                 "clipping %sabled, %s%s \n",
+                 format,
+                 (short)(ctx->data[1] & 0xffff),
+                 (ctx->data[1] >> 16) & 0xff,
+                 ctx->data[1] & (1 << 30) ? "en" : "dis",
+                 ctx->data[1] & (1 << 31) ? "solid pattern enabled, " : "",
+                 ctx->data[1] & (1 << 31) ?
+                 "mono pattern transparency enabled, " : "");
+
+}
+
+static int
+decode_2d(struct drm_intel_decode *ctx)
+{
+       unsigned int opcode, len;
+       uint32_t *data = ctx->data;
+
+       struct {
+               uint32_t opcode;
+               unsigned int min_len;
+               unsigned int max_len;
+               const char *name;
+       } opcodes_2d[] = {
+               { 0x40, 5, 5, "COLOR_BLT" },
+               { 0x43, 6, 6, "SRC_COPY_BLT" },
+               { 0x01, 8, 8, "XY_SETUP_BLT" },
+               { 0x11, 9, 9, "XY_SETUP_MONO_PATTERN_SL_BLT" },
+               { 0x03, 3, 3, "XY_SETUP_CLIP_BLT" },
+               { 0x24, 2, 2, "XY_PIXEL_BLT" },
+               { 0x25, 3, 3, "XY_SCANLINES_BLT" },
+               { 0x26, 4, 4, "Y_TEXT_BLT" },
+               { 0x31, 5, 134, "XY_TEXT_IMMEDIATE_BLT" },
+               { 0x50, 6, 6, "XY_COLOR_BLT" },
+               { 0x51, 6, 6, "XY_PAT_BLT" },
+               { 0x76, 8, 8, "XY_PAT_CHROMA_BLT" },
+               { 0x72, 7, 135, "XY_PAT_BLT_IMMEDIATE" },
+               { 0x77, 9, 137, "XY_PAT_CHROMA_BLT_IMMEDIATE" },
+               { 0x52, 9, 9, "XY_MONO_PAT_BLT" },
+               { 0x59, 7, 7, "XY_MONO_PAT_FIXED_BLT" },
+               { 0x53, 8, 8, "XY_SRC_COPY_BLT" },
+               { 0x54, 8, 8, "XY_MONO_SRC_COPY_BLT" },
+               { 0x71, 9, 137, "XY_MONO_SRC_COPY_IMMEDIATE_BLT" },
+               { 0x55, 9, 9, "XY_FULL_BLT" },
+               { 0x55, 9, 137, "XY_FULL_IMMEDIATE_PATTERN_BLT" },
+               { 0x56, 9, 9, "XY_FULL_MONO_SRC_BLT" },
+               { 0x75, 10, 138, "XY_FULL_MONO_SRC_IMMEDIATE_PATTERN_BLT" },
+               { 0x57, 12, 12, "XY_FULL_MONO_PATTERN_BLT" },
+               { 0x58, 12, 12, "XY_FULL_MONO_PATTERN_MONO_SRC_BLT"},
+       };
+
+       switch ((data[0] & 0x1fc00000) >> 22) {
+       case 0x25:
+               instr_out(ctx, 0,
+                         "XY_SCANLINES_BLT (pattern seed (%d, %d), dst tile %d)\n",
+                         (data[0] >> 12) & 0x8,
+                         (data[0] >> 8) & 0x8, (data[0] >> 11) & 1);
+
+               len = (data[0] & 0x000000ff) + 2;
+               if (len != 3)
+                       fprintf(out, "Bad count in XY_SCANLINES_BLT\n");
+
+               instr_out(ctx, 1, "dest (%d,%d)\n",
+                         data[1] & 0xffff, data[1] >> 16);
+               instr_out(ctx, 2, "dest (%d,%d)\n",
+                         data[2] & 0xffff, data[2] >> 16);
+               return len;
+       case 0x01:
+               decode_2d_br00(ctx, "XY_SETUP_BLT");
+
+               len = (data[0] & 0x000000ff) + 2;
+               if (len != 8)
+                       fprintf(out, "Bad count in XY_SETUP_BLT\n");
+
+               decode_2d_br01(ctx);
+               instr_out(ctx, 2, "cliprect (%d,%d)\n",
+                         data[2] & 0xffff, data[2] >> 16);
+               instr_out(ctx, 3, "cliprect (%d,%d)\n",
+                         data[3] & 0xffff, data[3] >> 16);
+               instr_out(ctx, 4, "setup dst offset 0x%08x\n",
+                         data[4]);
+               instr_out(ctx, 5, "setup background color\n");
+               instr_out(ctx, 6, "setup foreground color\n");
+               instr_out(ctx, 7, "color pattern offset\n");
+               return len;
+       case 0x03:
+               decode_2d_br00(ctx, "XY_SETUP_CLIP_BLT");
+
+               len = (data[0] & 0x000000ff) + 2;
+               if (len != 3)
+                       fprintf(out, "Bad count in XY_SETUP_CLIP_BLT\n");
+
+               instr_out(ctx, 1, "cliprect (%d,%d)\n",
+                         data[1] & 0xffff, data[2] >> 16);
+               instr_out(ctx, 2, "cliprect (%d,%d)\n",
+                         data[2] & 0xffff, data[3] >> 16);
+               return len;
+       case 0x11:
+               decode_2d_br00(ctx, "XY_SETUP_MONO_PATTERN_SL_BLT");
+
+               len = (data[0] & 0x000000ff) + 2;
+               if (len != 9)
+                       fprintf(out,
+                               "Bad count in XY_SETUP_MONO_PATTERN_SL_BLT\n");
+
+               decode_2d_br01(ctx);
+               instr_out(ctx, 2, "cliprect (%d,%d)\n",
+                         data[2] & 0xffff, data[2] >> 16);
+               instr_out(ctx, 3, "cliprect (%d,%d)\n",
+                         data[3] & 0xffff, data[3] >> 16);
+               instr_out(ctx, 4, "setup dst offset 0x%08x\n",
+                         data[4]);
+               instr_out(ctx, 5, "setup background color\n");
+               instr_out(ctx, 6, "setup foreground color\n");
+               instr_out(ctx, 7, "mono pattern dw0\n");
+               instr_out(ctx, 8, "mono pattern dw1\n");
+               return len;
+       case 0x50:
+               decode_2d_br00(ctx, "XY_COLOR_BLT");
+
+               len = (data[0] & 0x000000ff) + 2;
+               if (len != 6)
+                       fprintf(out, "Bad count in XY_COLOR_BLT\n");
+
+               decode_2d_br01(ctx);
+               instr_out(ctx, 2, "(%d,%d)\n",
+                         data[2] & 0xffff, data[2] >> 16);
+               instr_out(ctx, 3, "(%d,%d)\n",
+                         data[3] & 0xffff, data[3] >> 16);
+               instr_out(ctx, 4, "offset 0x%08x\n", data[4]);
+               instr_out(ctx, 5, "color\n");
+               return len;
+       case 0x53:
+               decode_2d_br00(ctx, "XY_SRC_COPY_BLT");
+
+               len = (data[0] & 0x000000ff) + 2;
+               if (len != 8)
+                       fprintf(out, "Bad count in XY_SRC_COPY_BLT\n");
+
+               decode_2d_br01(ctx);
+               instr_out(ctx, 2, "dst (%d,%d)\n",
+                         data[2] & 0xffff, data[2] >> 16);
+               instr_out(ctx, 3, "dst (%d,%d)\n",
+                         data[3] & 0xffff, data[3] >> 16);
+               instr_out(ctx, 4, "dst offset 0x%08x\n", data[4]);
+               instr_out(ctx, 5, "src (%d,%d)\n",
+                         data[5] & 0xffff, data[5] >> 16);
+               instr_out(ctx, 6, "src pitch %d\n",
+                         (short)(data[6] & 0xffff));
+               instr_out(ctx, 7, "src offset 0x%08x\n", data[7]);
+               return len;
+       }
+
+       for (opcode = 0; opcode < sizeof(opcodes_2d) / sizeof(opcodes_2d[0]);
+            opcode++) {
+               if ((data[0] & 0x1fc00000) >> 22 == opcodes_2d[opcode].opcode) {
+                       unsigned int i;
+
+                       len = 1;
+                       instr_out(ctx, 0, "%s\n",
+                                 opcodes_2d[opcode].name);
+                       if (opcodes_2d[opcode].max_len > 1) {
+                               len = (data[0] & 0x000000ff) + 2;
+                               if (len < opcodes_2d[opcode].min_len ||
+                                   len > opcodes_2d[opcode].max_len) {
+                                       fprintf(out, "Bad count in %s\n",
+                                               opcodes_2d[opcode].name);
+                               }
+                       }
+
+                       for (i = 1; i < len; i++) {
+                               instr_out(ctx, i, "dword %d\n", i);
+                       }
+
+                       return len;
+               }
+       }
+
+       instr_out(ctx, 0, "2D UNKNOWN\n");
+       return 1;
+}
+
+static int
+decode_3d_1c(struct drm_intel_decode *ctx)
+{
+       uint32_t *data = ctx->data;
+       uint32_t opcode;
+
+       opcode = (data[0] & 0x00f80000) >> 19;
+
+       switch (opcode) {
+       case 0x11:
+               instr_out(ctx, 0,
+                         "3DSTATE_DEPTH_SUBRECTANGLE_DISABLE\n");
+               return 1;
+       case 0x10:
+               instr_out(ctx, 0, "3DSTATE_SCISSOR_ENABLE %s\n",
+                         data[0] & 1 ? "enabled" : "disabled");
+               return 1;
+       case 0x01:
+               instr_out(ctx, 0, "3DSTATE_MAP_COORD_SET_I830\n");
+               return 1;
+       case 0x0a:
+               instr_out(ctx, 0, "3DSTATE_MAP_CUBE_I830\n");
+               return 1;
+       case 0x05:
+               instr_out(ctx, 0, "3DSTATE_MAP_TEX_STREAM_I830\n");
+               return 1;
+       }
+
+       instr_out(ctx, 0, "3D UNKNOWN: 3d_1c opcode = 0x%x\n",
+                 opcode);
+       return 1;
+}
+
+/** Sets the string dstname to describe the destination of the PS instruction */
+static void
+i915_get_instruction_dst(uint32_t *data, int i, char *dstname, int do_mask)
+{
+       uint32_t a0 = data[i];
+       int dst_nr = (a0 >> 14) & 0xf;
+       char dstmask[8];
+       const char *sat;
+
+       if (do_mask) {
+               if (((a0 >> 10) & 0xf) == 0xf) {
+                       dstmask[0] = 0;
+               } else {
+                       int dstmask_index = 0;
+
+                       dstmask[dstmask_index++] = '.';
+                       if (a0 & (1 << 10))
+                               dstmask[dstmask_index++] = 'x';
+                       if (a0 & (1 << 11))
+                               dstmask[dstmask_index++] = 'y';
+                       if (a0 & (1 << 12))
+                               dstmask[dstmask_index++] = 'z';
+                       if (a0 & (1 << 13))
+                               dstmask[dstmask_index++] = 'w';
+                       dstmask[dstmask_index++] = 0;
+               }
+
+               if (a0 & (1 << 22))
+                       sat = ".sat";
+               else
+                       sat = "";
+       } else {
+               dstmask[0] = 0;
+               sat = "";
+       }
+
+       switch ((a0 >> 19) & 0x7) {
+       case 0:
+               if (dst_nr > 15)
+                       fprintf(out, "bad destination reg R%d\n", dst_nr);
+               sprintf(dstname, "R%d%s%s", dst_nr, dstmask, sat);
+               break;
+       case 4:
+               if (dst_nr > 0)
+                       fprintf(out, "bad destination reg oC%d\n", dst_nr);
+               sprintf(dstname, "oC%s%s", dstmask, sat);
+               break;
+       case 5:
+               if (dst_nr > 0)
+                       fprintf(out, "bad destination reg oD%d\n", dst_nr);
+               sprintf(dstname, "oD%s%s", dstmask, sat);
+               break;
+       case 6:
+               if (dst_nr > 3)
+                       fprintf(out, "bad destination reg U%d\n", dst_nr);
+               sprintf(dstname, "U%d%s%s", dst_nr, dstmask, sat);
+               break;
+       default:
+               sprintf(dstname, "RESERVED");
+               break;
+       }
+}
+
+static const char *
+i915_get_channel_swizzle(uint32_t select)
+{
+       switch (select & 0x7) {
+       case 0:
+               return (select & 8) ? "-x" : "x";
+       case 1:
+               return (select & 8) ? "-y" : "y";
+       case 2:
+               return (select & 8) ? "-z" : "z";
+       case 3:
+               return (select & 8) ? "-w" : "w";
+       case 4:
+               return (select & 8) ? "-0" : "0";
+       case 5:
+               return (select & 8) ? "-1" : "1";
+       default:
+               return (select & 8) ? "-bad" : "bad";
+       }
+}
+
+static void
+i915_get_instruction_src_name(uint32_t src_type, uint32_t src_nr, char *name)
+{
+       switch (src_type) {
+       case 0:
+               sprintf(name, "R%d", src_nr);
+               if (src_nr > 15)
+                       fprintf(out, "bad src reg %s\n", name);
+               break;
+       case 1:
+               if (src_nr < 8)
+                       sprintf(name, "T%d", src_nr);
+               else if (src_nr == 8)
+                       sprintf(name, "DIFFUSE");
+               else if (src_nr == 9)
+                       sprintf(name, "SPECULAR");
+               else if (src_nr == 10)
+                       sprintf(name, "FOG");
+               else {
+                       fprintf(out, "bad src reg T%d\n", src_nr);
+                       sprintf(name, "RESERVED");
+               }
+               break;
+       case 2:
+               sprintf(name, "C%d", src_nr);
+               if (src_nr > 31)
+                       fprintf(out, "bad src reg %s\n", name);
+               break;
+       case 4:
+               sprintf(name, "oC");
+               if (src_nr > 0)
+                       fprintf(out, "bad src reg oC%d\n", src_nr);
+               break;
+       case 5:
+               sprintf(name, "oD");
+               if (src_nr > 0)
+                       fprintf(out, "bad src reg oD%d\n", src_nr);
+               break;
+       case 6:
+               sprintf(name, "U%d", src_nr);
+               if (src_nr > 3)
+                       fprintf(out, "bad src reg %s\n", name);
+               break;
+       default:
+               fprintf(out, "bad src reg type %d\n", src_type);
+               sprintf(name, "RESERVED");
+               break;
+       }
+}
+
+static void i915_get_instruction_src0(uint32_t *data, int i, char *srcname)
+{
+       uint32_t a0 = data[i];
+       uint32_t a1 = data[i + 1];
+       int src_nr = (a0 >> 2) & 0x1f;
+       const char *swizzle_x = i915_get_channel_swizzle((a1 >> 28) & 0xf);
+       const char *swizzle_y = i915_get_channel_swizzle((a1 >> 24) & 0xf);
+       const char *swizzle_z = i915_get_channel_swizzle((a1 >> 20) & 0xf);
+       const char *swizzle_w = i915_get_channel_swizzle((a1 >> 16) & 0xf);
+       char swizzle[100];
+
+       i915_get_instruction_src_name((a0 >> 7) & 0x7, src_nr, srcname);
+       sprintf(swizzle, ".%s%s%s%s", swizzle_x, swizzle_y, swizzle_z,
+               swizzle_w);
+       if (strcmp(swizzle, ".xyzw") != 0)
+               strcat(srcname, swizzle);
+}
+
+static void i915_get_instruction_src1(uint32_t *data, int i, char *srcname)
+{
+       uint32_t a1 = data[i + 1];
+       uint32_t a2 = data[i + 2];
+       int src_nr = (a1 >> 8) & 0x1f;
+       const char *swizzle_x = i915_get_channel_swizzle((a1 >> 4) & 0xf);
+       const char *swizzle_y = i915_get_channel_swizzle((a1 >> 0) & 0xf);
+       const char *swizzle_z = i915_get_channel_swizzle((a2 >> 28) & 0xf);
+       const char *swizzle_w = i915_get_channel_swizzle((a2 >> 24) & 0xf);
+       char swizzle[100];
+
+       i915_get_instruction_src_name((a1 >> 13) & 0x7, src_nr, srcname);
+       sprintf(swizzle, ".%s%s%s%s", swizzle_x, swizzle_y, swizzle_z,
+               swizzle_w);
+       if (strcmp(swizzle, ".xyzw") != 0)
+               strcat(srcname, swizzle);
+}
+
+static void i915_get_instruction_src2(uint32_t *data, int i, char *srcname)
+{
+       uint32_t a2 = data[i + 2];
+       int src_nr = (a2 >> 16) & 0x1f;
+       const char *swizzle_x = i915_get_channel_swizzle((a2 >> 12) & 0xf);
+       const char *swizzle_y = i915_get_channel_swizzle((a2 >> 8) & 0xf);
+       const char *swizzle_z = i915_get_channel_swizzle((a2 >> 4) & 0xf);
+       const char *swizzle_w = i915_get_channel_swizzle((a2 >> 0) & 0xf);
+       char swizzle[100];
+
+       i915_get_instruction_src_name((a2 >> 21) & 0x7, src_nr, srcname);
+       sprintf(swizzle, ".%s%s%s%s", swizzle_x, swizzle_y, swizzle_z,
+               swizzle_w);
+       if (strcmp(swizzle, ".xyzw") != 0)
+               strcat(srcname, swizzle);
+}
+
+static void
+i915_get_instruction_addr(uint32_t src_type, uint32_t src_nr, char *name)
+{
+       switch (src_type) {
+       case 0:
+               sprintf(name, "R%d", src_nr);
+               if (src_nr > 15)
+                       fprintf(out, "bad src reg %s\n", name);
+               break;
+       case 1:
+               if (src_nr < 8)
+                       sprintf(name, "T%d", src_nr);
+               else if (src_nr == 8)
+                       sprintf(name, "DIFFUSE");
+               else if (src_nr == 9)
+                       sprintf(name, "SPECULAR");
+               else if (src_nr == 10)
+                       sprintf(name, "FOG");
+               else {
+                       fprintf(out, "bad src reg T%d\n", src_nr);
+                       sprintf(name, "RESERVED");
+               }
+               break;
+       case 4:
+               sprintf(name, "oC");
+               if (src_nr > 0)
+                       fprintf(out, "bad src reg oC%d\n", src_nr);
+               break;
+       case 5:
+               sprintf(name, "oD");
+               if (src_nr > 0)
+                       fprintf(out, "bad src reg oD%d\n", src_nr);
+               break;
+       default:
+               fprintf(out, "bad src reg type %d\n", src_type);
+               sprintf(name, "RESERVED");
+               break;
+       }
+}
+
+static void
+i915_decode_alu1(struct drm_intel_decode *ctx,
+                int i, char *instr_prefix, const char *op_name)
+{
+       char dst[100], src0[100];
+
+       i915_get_instruction_dst(ctx->data, i, dst, 1);
+       i915_get_instruction_src0(ctx->data, i, src0);
+
+       instr_out(ctx, i++, "%s: %s %s, %s\n", instr_prefix,
+                 op_name, dst, src0);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+}
+
+static void
+i915_decode_alu2(struct drm_intel_decode *ctx,
+                int i, char *instr_prefix, const char *op_name)
+{
+       char dst[100], src0[100], src1[100];
+
+       i915_get_instruction_dst(ctx->data, i, dst, 1);
+       i915_get_instruction_src0(ctx->data, i, src0);
+       i915_get_instruction_src1(ctx->data, i, src1);
+
+       instr_out(ctx, i++, "%s: %s %s, %s, %s\n", instr_prefix,
+                 op_name, dst, src0, src1);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+}
+
+static void
+i915_decode_alu3(struct drm_intel_decode *ctx,
+                int i, char *instr_prefix, const char *op_name)
+{
+       char dst[100], src0[100], src1[100], src2[100];
+
+       i915_get_instruction_dst(ctx->data, i, dst, 1);
+       i915_get_instruction_src0(ctx->data, i, src0);
+       i915_get_instruction_src1(ctx->data, i, src1);
+       i915_get_instruction_src2(ctx->data, i, src2);
+
+       instr_out(ctx, i++, "%s: %s %s, %s, %s, %s\n", instr_prefix,
+                 op_name, dst, src0, src1, src2);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+}
+
+static void
+i915_decode_tex(struct drm_intel_decode *ctx, int i,
+               const char *instr_prefix, const char *tex_name)
+{
+       uint32_t t0 = ctx->data[i];
+       uint32_t t1 = ctx->data[i + 1];
+       char dst_name[100];
+       char addr_name[100];
+       int sampler_nr;
+
+       i915_get_instruction_dst(ctx->data, i, dst_name, 0);
+       i915_get_instruction_addr((t1 >> 24) & 0x7,
+                                 (t1 >> 17) & 0xf, addr_name);
+       sampler_nr = t0 & 0xf;
+
+       instr_out(ctx, i++, "%s: %s %s, S%d, %s\n", instr_prefix,
+                 tex_name, dst_name, sampler_nr, addr_name);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+       instr_out(ctx, i++, "%s\n", instr_prefix);
+}
+
+static void
+i915_decode_dcl(struct drm_intel_decode *ctx, int i, char *instr_prefix)
+{
+       uint32_t d0 = ctx->data[i];
+       const char *sampletype;
+       int dcl_nr = (d0 >> 14) & 0xf;
+       const char *dcl_x = d0 & (1 << 10) ? "x" : "";
+       const char *dcl_y = d0 & (1 << 11) ? "y" : "";
+       const char *dcl_z = d0 & (1 << 12) ? "z" : "";
+       const char *dcl_w = d0 & (1 << 13) ? "w" : "";
+       char dcl_mask[10];
+
+       switch ((d0 >> 19) & 0x3) {
+       case 1:
+               sprintf(dcl_mask, ".%s%s%s%s", dcl_x, dcl_y, dcl_z, dcl_w);
+               if (strcmp(dcl_mask, ".") == 0)
+                       fprintf(out, "bad (empty) dcl mask\n");
+
+               if (dcl_nr > 10)
+                       fprintf(out, "bad T%d dcl register number\n", dcl_nr);
+               if (dcl_nr < 8) {
+                       if (strcmp(dcl_mask, ".x") != 0 &&
+                           strcmp(dcl_mask, ".xy") != 0 &&
+                           strcmp(dcl_mask, ".xz") != 0 &&
+                           strcmp(dcl_mask, ".w") != 0 &&
+                           strcmp(dcl_mask, ".xyzw") != 0) {
+                               fprintf(out, "bad T%d.%s dcl mask\n", dcl_nr,
+                                       dcl_mask);
+                       }
+                       instr_out(ctx, i++, "%s: DCL T%d%s\n",
+                                 instr_prefix, dcl_nr, dcl_mask);
+               } else {
+                       if (strcmp(dcl_mask, ".xz") == 0)
+                               fprintf(out, "errataed bad dcl mask %s\n",
+                                       dcl_mask);
+                       else if (strcmp(dcl_mask, ".xw") == 0)
+                               fprintf(out, "errataed bad dcl mask %s\n",
+                                       dcl_mask);
+                       else if (strcmp(dcl_mask, ".xzw") == 0)
+                               fprintf(out, "errataed bad dcl mask %s\n",
+                                       dcl_mask);
+
+                       if (dcl_nr == 8) {
+                               instr_out(ctx, i++,
+                                         "%s: DCL DIFFUSE%s\n", instr_prefix,
+                                         dcl_mask);
+                       } else if (dcl_nr == 9) {
+                               instr_out(ctx, i++,
+                                         "%s: DCL SPECULAR%s\n", instr_prefix,
+                                         dcl_mask);
+                       } else if (dcl_nr == 10) {
+                               instr_out(ctx, i++,
+                                         "%s: DCL FOG%s\n", instr_prefix,
+                                         dcl_mask);
+                       }
+               }
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               break;
+       case 3:
+               switch ((d0 >> 22) & 0x3) {
+               case 0:
+                       sampletype = "2D";
+                       break;
+               case 1:
+                       sampletype = "CUBE";
+                       break;
+               case 2:
+                       sampletype = "3D";
+                       break;
+               default:
+                       sampletype = "RESERVED";
+                       break;
+               }
+               if (dcl_nr > 15)
+                       fprintf(out, "bad S%d dcl register number\n", dcl_nr);
+               instr_out(ctx, i++, "%s: DCL S%d %s\n",
+                         instr_prefix, dcl_nr, sampletype);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               break;
+       default:
+               instr_out(ctx, i++, "%s: DCL RESERVED%d\n",
+                         instr_prefix, dcl_nr);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+       }
+}
+
+static void
+i915_decode_instruction(struct drm_intel_decode *ctx,
+                       int i, char *instr_prefix)
+{
+       switch ((ctx->data[i] >> 24) & 0x1f) {
+       case 0x0:
+               instr_out(ctx, i++, "%s: NOP\n", instr_prefix);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               break;
+       case 0x01:
+               i915_decode_alu2(ctx, i, instr_prefix, "ADD");
+               break;
+       case 0x02:
+               i915_decode_alu1(ctx, i, instr_prefix, "MOV");
+               break;
+       case 0x03:
+               i915_decode_alu2(ctx, i, instr_prefix, "MUL");
+               break;
+       case 0x04:
+               i915_decode_alu3(ctx, i, instr_prefix, "MAD");
+               break;
+       case 0x05:
+               i915_decode_alu3(ctx, i, instr_prefix, "DP2ADD");
+               break;
+       case 0x06:
+               i915_decode_alu2(ctx, i, instr_prefix, "DP3");
+               break;
+       case 0x07:
+               i915_decode_alu2(ctx, i, instr_prefix, "DP4");
+               break;
+       case 0x08:
+               i915_decode_alu1(ctx, i, instr_prefix, "FRC");
+               break;
+       case 0x09:
+               i915_decode_alu1(ctx, i, instr_prefix, "RCP");
+               break;
+       case 0x0a:
+               i915_decode_alu1(ctx, i, instr_prefix, "RSQ");
+               break;
+       case 0x0b:
+               i915_decode_alu1(ctx, i, instr_prefix, "EXP");
+               break;
+       case 0x0c:
+               i915_decode_alu1(ctx, i, instr_prefix, "LOG");
+               break;
+       case 0x0d:
+               i915_decode_alu2(ctx, i, instr_prefix, "CMP");
+               break;
+       case 0x0e:
+               i915_decode_alu2(ctx, i, instr_prefix, "MIN");
+               break;
+       case 0x0f:
+               i915_decode_alu2(ctx, i, instr_prefix, "MAX");
+               break;
+       case 0x10:
+               i915_decode_alu1(ctx, i, instr_prefix, "FLR");
+               break;
+       case 0x11:
+               i915_decode_alu1(ctx, i, instr_prefix, "MOD");
+               break;
+       case 0x12:
+               i915_decode_alu1(ctx, i, instr_prefix, "TRC");
+               break;
+       case 0x13:
+               i915_decode_alu2(ctx, i, instr_prefix, "SGE");
+               break;
+       case 0x14:
+               i915_decode_alu2(ctx, i, instr_prefix, "SLT");
+               break;
+       case 0x15:
+               i915_decode_tex(ctx, i, instr_prefix, "TEXLD");
+               break;
+       case 0x16:
+               i915_decode_tex(ctx, i, instr_prefix, "TEXLDP");
+               break;
+       case 0x17:
+               i915_decode_tex(ctx, i, instr_prefix, "TEXLDB");
+               break;
+       case 0x19:
+               i915_decode_dcl(ctx, i, instr_prefix);
+               break;
+       default:
+               instr_out(ctx, i++, "%s: unknown\n", instr_prefix);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               instr_out(ctx, i++, "%s\n", instr_prefix);
+               break;
+       }
+}
+
+static const char *
+decode_compare_func(uint32_t op)
+{
+       switch (op & 0x7) {
+       case 0:
+               return "always";
+       case 1:
+               return "never";
+       case 2:
+               return "less";
+       case 3:
+               return "equal";
+       case 4:
+               return "lequal";
+       case 5:
+               return "greater";
+       case 6:
+               return "notequal";
+       case 7:
+               return "gequal";
+       }
+       return "";
+}
+
+static const char *
+decode_stencil_op(uint32_t op)
+{
+       switch (op & 0x7) {
+       case 0:
+               return "keep";
+       case 1:
+               return "zero";
+       case 2:
+               return "replace";
+       case 3:
+               return "incr_sat";
+       case 4:
+               return "decr_sat";
+       case 5:
+               return "greater";
+       case 6:
+               return "incr";
+       case 7:
+               return "decr";
+       }
+       return "";
+}
+
+#if 0
+static const char *
+decode_logic_op(uint32_t op)
+{
+       switch (op & 0xf) {
+       case 0:
+               return "clear";
+       case 1:
+               return "nor";
+       case 2:
+               return "and_inv";
+       case 3:
+               return "copy_inv";
+       case 4:
+               return "and_rvrse";
+       case 5:
+               return "inv";
+       case 6:
+               return "xor";
+       case 7:
+               return "nand";
+       case 8:
+               return "and";
+       case 9:
+               return "equiv";
+       case 10:
+               return "noop";
+       case 11:
+               return "or_inv";
+       case 12:
+               return "copy";
+       case 13:
+               return "or_rvrse";
+       case 14:
+               return "or";
+       case 15:
+               return "set";
+       }
+       return "";
+}
+#endif
+
+static const char *
+decode_blend_fact(uint32_t op)
+{
+       switch (op & 0xf) {
+       case 1:
+               return "zero";
+       case 2:
+               return "one";
+       case 3:
+               return "src_colr";
+       case 4:
+               return "inv_src_colr";
+       case 5:
+               return "src_alpha";
+       case 6:
+               return "inv_src_alpha";
+       case 7:
+               return "dst_alpha";
+       case 8:
+               return "inv_dst_alpha";
+       case 9:
+               return "dst_colr";
+       case 10:
+               return "inv_dst_colr";
+       case 11:
+               return "src_alpha_sat";
+       case 12:
+               return "cnst_colr";
+       case 13:
+               return "inv_cnst_colr";
+       case 14:
+               return "cnst_alpha";
+       case 15:
+               return "inv_const_alpha";
+       }
+       return "";
+}
+
+static const char *
+decode_tex_coord_mode(uint32_t mode)
+{
+       switch (mode & 0x7) {
+       case 0:
+               return "wrap";
+       case 1:
+               return "mirror";
+       case 2:
+               return "clamp_edge";
+       case 3:
+               return "cube";
+       case 4:
+               return "clamp_border";
+       case 5:
+               return "mirror_once";
+       }
+       return "";
+}
+
+static const char *
+decode_sample_filter(uint32_t mode)
+{
+       switch (mode & 0x7) {
+       case 0:
+               return "nearest";
+       case 1:
+               return "linear";
+       case 2:
+               return "anisotropic";
+       case 3:
+               return "4x4_1";
+       case 4:
+               return "4x4_2";
+       case 5:
+               return "4x4_flat";
+       case 6:
+               return "6x5_mono";
+       }
+       return "";
+}
+
+static int
+decode_3d_1d(struct drm_intel_decode *ctx)
+{
+       unsigned int len, i, c, idx, word, map, sampler, instr;
+       const char *format, *zformat, *type;
+       uint32_t opcode;
+       uint32_t *data = ctx->data;
+       uint32_t devid = ctx->devid;
+
+       struct {
+               uint32_t opcode;
+               int i830_only;
+               unsigned int min_len;
+               unsigned int max_len;
+               const char *name;
+       } opcodes_3d_1d[] = {
+               { 0x86, 0, 4, 4, "3DSTATE_CHROMA_KEY" },
+               { 0x88, 0, 2, 2, "3DSTATE_CONSTANT_BLEND_COLOR" },
+               { 0x99, 0, 2, 2, "3DSTATE_DEFAULT_DIFFUSE" },
+               { 0x9a, 0, 2, 2, "3DSTATE_DEFAULT_SPECULAR" },
+               { 0x98, 0, 2, 2, "3DSTATE_DEFAULT_Z" },
+               { 0x97, 0, 2, 2, "3DSTATE_DEPTH_OFFSET_SCALE" },
+               { 0x9d, 0, 65, 65, "3DSTATE_FILTER_COEFFICIENTS_4X4" },
+               { 0x9e, 0, 4, 4, "3DSTATE_MONO_FILTER" },
+               { 0x89, 0, 4, 4, "3DSTATE_FOG_MODE" },
+               { 0x8f, 0, 2, 16, "3DSTATE_MAP_PALLETE_LOAD_32" },
+               { 0x83, 0, 2, 2, "3DSTATE_SPAN_STIPPLE" },
+               { 0x8c, 1, 2, 2, "3DSTATE_MAP_COORD_TRANSFORM_I830" },
+               { 0x8b, 1, 2, 2, "3DSTATE_MAP_VERTEX_TRANSFORM_I830" },
+               { 0x8d, 1, 3, 3, "3DSTATE_W_STATE_I830" },
+               { 0x01, 1, 2, 2, "3DSTATE_COLOR_FACTOR_I830" },
+               { 0x02, 1, 2, 2, "3DSTATE_MAP_COORD_SETBIND_I830"},
+       }, *opcode_3d_1d;
+
+       opcode = (data[0] & 0x00ff0000) >> 16;
+
+       switch (opcode) {
+       case 0x07:
+               /* This instruction is unusual.  A 0 length means just
+                * 1 DWORD instead of 2.  The 0 length is specified in
+                * one place to be unsupported, but stated to be
+                * required in another, and 0 length LOAD_INDIRECTs
+                * appear to cause no harm at least.
+                */
+               instr_out(ctx, 0, "3DSTATE_LOAD_INDIRECT\n");
+               len = (data[0] & 0x000000ff) + 1;
+               i = 1;
+               if (data[0] & (0x01 << 8)) {
+                       instr_out(ctx, i++, "SIS.0\n");
+                       instr_out(ctx, i++, "SIS.1\n");
+               }
+               if (data[0] & (0x02 << 8)) {
+                       instr_out(ctx, i++, "DIS.0\n");
+               }
+               if (data[0] & (0x04 << 8)) {
+                       instr_out(ctx, i++, "SSB.0\n");
+                       instr_out(ctx, i++, "SSB.1\n");
+               }
+               if (data[0] & (0x08 << 8)) {
+                       instr_out(ctx, i++, "MSB.0\n");
+                       instr_out(ctx, i++, "MSB.1\n");
+               }
+               if (data[0] & (0x10 << 8)) {
+                       instr_out(ctx, i++, "PSP.0\n");
+                       instr_out(ctx, i++, "PSP.1\n");
+               }
+               if (data[0] & (0x20 << 8)) {
+                       instr_out(ctx, i++, "PSC.0\n");
+                       instr_out(ctx, i++, "PSC.1\n");
+               }
+               if (len != i) {
+                       fprintf(out, "Bad count in 3DSTATE_LOAD_INDIRECT\n");
+                       return len;
+               }
+               return len;
+       case 0x04:
+               instr_out(ctx, 0,
+                         "3DSTATE_LOAD_STATE_IMMEDIATE_1\n");
+               len = (data[0] & 0x0000000f) + 2;
+               i = 1;
+               for (word = 0; word <= 8; word++) {
+                       if (data[0] & (1 << (4 + word))) {
+                               /* save vertex state for decode */
+                               if (!IS_GEN2(devid)) {
+                                       int tex_num;
+
+                                       if (word == 2) {
+                                               saved_s2_set = 1;
+                                               saved_s2 = data[i];
+                                       }
+                                       if (word == 4) {
+                                               saved_s4_set = 1;
+                                               saved_s4 = data[i];
+                                       }
+
+                                       switch (word) {
+                                       case 0:
+                                               instr_out(ctx, i,
+                                                         "S0: vbo offset: 0x%08x%s\n",
+                                                         data[i] & (~1),
+                                                         data[i] & 1 ?
+                                                         ", auto cache invalidate disabled"
+                                                         : "");
+                                               break;
+                                       case 1:
+                                               instr_out(ctx, i,
+                                                         "S1: vertex width: %i, vertex pitch: %i\n",
+                                                         (data[i] >> 24) &
+                                                         0x3f,
+                                                         (data[i] >> 16) &
+                                                         0x3f);
+                                               break;
+                                       case 2:
+                                               instr_out(ctx, i,
+                                                         "S2: texcoord formats: ");
+                                               for (tex_num = 0;
+                                                    tex_num < 8; tex_num++) {
+                                                       switch ((data[i] >>
+                                                                tex_num *
+                                                                4) & 0xf) {
+                                                       case 0:
+                                                               fprintf(out,
+                                                                       "%i=2D ",
+                                                                       tex_num);
+                                                               break;
+                                                       case 1:
+                                                               fprintf(out,
+                                                                       "%i=3D ",
+                                                                       tex_num);
+                                                               break;
+                                                       case 2:
+                                                               fprintf(out,
+                                                                       "%i=4D ",
+                                                                       tex_num);
+                                                               break;
+                                                       case 3:
+                                                               fprintf(out,
+                                                                       "%i=1D ",
+                                                                       tex_num);
+                                                               break;
+                                                       case 4:
+                                                               fprintf(out,
+                                                                       "%i=2D_16 ",
+                                                                       tex_num);
+                                                               break;
+                                                       case 5:
+                                                               fprintf(out,
+                                                                       "%i=4D_16 ",
+                                                                       tex_num);
+                                                               break;
+                                                       case 0xf:
+                                                               fprintf(out,
+                                                                       "%i=NP ",
+                                                                       tex_num);
+                                                               break;
+                                                       }
+                                               }
+                                               fprintf(out, "\n");
+
+                                               break;
+                                       case 3:
+                                               instr_out(ctx, i,
+                                                         "S3: not documented\n");
+                                               break;
+                                       case 4:
+                                               {
+                                                       const char *cullmode = "";
+                                                       const char *vfmt_xyzw = "";
+                                                       switch ((data[i] >> 13)
+                                                               & 0x3) {
+                                                       case 0:
+                                                               cullmode =
+                                                                   "both";
+                                                               break;
+                                                       case 1:
+                                                               cullmode =
+                                                                   "none";
+                                                               break;
+                                                       case 2:
+                                                               cullmode = "cw";
+                                                               break;
+                                                       case 3:
+                                                               cullmode =
+                                                                   "ccw";
+                                                               break;
+                                                       }
+                                                       switch (data[i] &
+                                                               (7 << 6 | 1 <<
+                                                                2)) {
+                                                       case 1 << 6:
+                                                               vfmt_xyzw =
+                                                                   "XYZ,";
+                                                               break;
+                                                       case 2 << 6:
+                                                               vfmt_xyzw =
+                                                                   "XYZW,";
+                                                               break;
+                                                       case 3 << 6:
+                                                               vfmt_xyzw =
+                                                                   "XY,";
+                                                               break;
+                                                       case 4 << 6:
+                                                               vfmt_xyzw =
+                                                                   "XYW,";
+                                                               break;
+                                                       case 1 << 6 | 1 << 2:
+                                                               vfmt_xyzw =
+                                                                   "XYZF,";
+                                                               break;
+                                                       case 2 << 6 | 1 << 2:
+                                                               vfmt_xyzw =
+                                                                   "XYZWF,";
+                                                               break;
+                                                       case 3 << 6 | 1 << 2:
+                                                               vfmt_xyzw =
+                                                                   "XYF,";
+                                                               break;
+                                                       case 4 << 6 | 1 << 2:
+                                                               vfmt_xyzw =
+                                                                   "XYWF,";
+                                                               break;
+                                                       }
+                                                       instr_out(ctx, i,
+                                                                 "S4: point_width=%i, line_width=%.1f,"
+                                                                 "%s%s%s%s%s cullmode=%s, vfmt=%s%s%s%s%s%s "
+                                                                 "%s%s%s%s%s\n",
+                                                                 (data[i] >>
+                                                                  23) & 0x1ff,
+                                                                 ((data[i] >>
+                                                                   19) & 0xf) /
+                                                                 2.0,
+                                                                 data[i] & (0xf
+                                                                            <<
+                                                                            15)
+                                                                 ?
+                                                                 " flatshade="
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            18)
+                                                                 ? "Alpha," :
+                                                                 "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            17)
+                                                                 ? "Fog," : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            16)
+                                                                 ? "Specular,"
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            15)
+                                                                 ? "Color," :
+                                                                 "", cullmode,
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            12)
+                                                                 ?
+                                                                 "PointWidth,"
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            11)
+                                                                 ? "SpecFog," :
+                                                                 "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            10)
+                                                                 ? "Color," :
+                                                                 "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            9)
+                                                                 ? "DepthOfs,"
+                                                                 : "",
+                                                                 vfmt_xyzw,
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            9)
+                                                                 ? "FogParam,"
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            5)
+                                                                 ?
+                                                                 "force default diffuse, "
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            4)
+                                                                 ?
+                                                                 "force default specular, "
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            3)
+                                                                 ?
+                                                                 "local depth ofs enable, "
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            1)
+                                                                 ?
+                                                                 "point sprite enable, "
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            0)
+                                                                 ?
+                                                                 "line AA enable, "
+                                                                 : "");
+                                                       break;
+                                               }
+                                       case 5:
+                                               {
+                                                       instr_out(ctx, i,
+                                                                 "S5:%s%s%s%s%s"
+                                                                 "%s%s%s%s stencil_ref=0x%x, stencil_test=%s, "
+                                                                 "stencil_fail=%s, stencil_pass_z_fail=%s, "
+                                                                 "stencil_pass_z_pass=%s, %s%s%s%s\n",
+                                                                 data[i] & (0xf
+                                                                            <<
+                                                                            28)
+                                                                 ?
+                                                                 " write_disable="
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            31)
+                                                                 ? "Alpha," :
+                                                                 "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            30)
+                                                                 ? "Red," : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            29)
+                                                                 ? "Green," :
+                                                                 "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            28)
+                                                                 ? "Blue," :
+                                                                 "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            27)
+                                                                 ?
+                                                                 " force default point size,"
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            26)
+                                                                 ?
+                                                                 " last pixel enable,"
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            25)
+                                                                 ?
+                                                                 " global depth ofs enable,"
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            24)
+                                                                 ?
+                                                                 " fog enable,"
+                                                                 : "",
+                                                                 (data[i] >>
+                                                                  16) & 0xff,
+                                                                 decode_compare_func
+                                                                 (data[i] >>
+                                                                  13),
+                                                                 decode_stencil_op
+                                                                 (data[i] >>
+                                                                  10),
+                                                                 decode_stencil_op
+                                                                 (data[i] >>
+                                                                  7),
+                                                                 decode_stencil_op
+                                                                 (data[i] >>
+                                                                  4),
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            3)
+                                                                 ?
+                                                                 "stencil write enable, "
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            2)
+                                                                 ?
+                                                                 "stencil test enable, "
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            1)
+                                                                 ?
+                                                                 "color dither enable, "
+                                                                 : "",
+                                                                 data[i] & (1
+                                                                            <<
+                                                                            0)
+                                                                 ?
+                                                                 "logicop enable, "
+                                                                 : "");
+                                               }
+                                               break;
+                                       case 6:
+                                               instr_out(ctx, i,
+                                                         "S6: %salpha_test=%s, alpha_ref=0x%x, "
+                                                         "depth_test=%s, %ssrc_blnd_fct=%s, dst_blnd_fct=%s, "
+                                                         "%s%stristrip_provoking_vertex=%i\n",
+                                                         data[i] & (1 << 31) ?
+                                                         "alpha test enable, "
+                                                         : "",
+                                                         decode_compare_func
+                                                         (data[i] >> 28),
+                                                         data[i] & (0xff <<
+                                                                    20),
+                                                         decode_compare_func
+                                                         (data[i] >> 16),
+                                                         data[i] & (1 << 15) ?
+                                                         "cbuf blend enable, "
+                                                         : "",
+                                                         decode_blend_fact(data
+                                                                           [i]
+                                                                           >>
+                                                                           8),
+                                                         decode_blend_fact(data
+                                                                           [i]
+                                                                           >>
+                                                                           4),
+                                                         data[i] & (1 << 3) ?
+                                                         "depth write enable, "
+                                                         : "",
+                                                         data[i] & (1 << 2) ?
+                                                         "cbuf write enable, "
+                                                         : "",
+                                                         data[i] & (0x3));
+                                               break;
+                                       case 7:
+                                               instr_out(ctx, i,
+                                                         "S7: depth offset constant: 0x%08x\n",
+                                                         data[i]);
+                                               break;
+                                       }
+                               } else {
+                                       instr_out(ctx, i,
+                                                 "S%d: 0x%08x\n", i, data[i]);
+                               }
+                               i++;
+                       }
+               }
+               if (len != i) {
+                       fprintf(out,
+                               "Bad count in 3DSTATE_LOAD_STATE_IMMEDIATE_1\n");
+               }
+               return len;
+       case 0x03:
+               instr_out(ctx, 0,
+                         "3DSTATE_LOAD_STATE_IMMEDIATE_2\n");
+               len = (data[0] & 0x0000000f) + 2;
+               i = 1;
+               for (word = 6; word <= 14; word++) {
+                       if (data[0] & (1 << word)) {
+                               if (word == 6)
+                                       instr_out(ctx, i++,
+                                                 "TBCF\n");
+                               else if (word >= 7 && word <= 10) {
+                                       instr_out(ctx, i++,
+                                                 "TB%dC\n", word - 7);
+                                       instr_out(ctx, i++,
+                                                 "TB%dA\n", word - 7);
+                               } else if (word >= 11 && word <= 14) {
+                                       instr_out(ctx, i,
+                                                 "TM%dS0: offset=0x%08x, %s\n",
+                                                 word - 11,
+                                                 data[i] & 0xfffffffe,
+                                                 data[i] & 1 ? "use fence" :
+                                                 "");
+                                       i++;
+                                       instr_out(ctx, i,
+                                                 "TM%dS1: height=%i, width=%i, %s\n",
+                                                 word - 11, data[i] >> 21,
+                                                 (data[i] >> 10) & 0x3ff,
+                                                 data[i] & 2 ? (data[i] & 1 ?
+                                                                "y-tiled" :
+                                                                "x-tiled") :
+                                                 "");
+                                       i++;
+                                       instr_out(ctx, i,
+                                                 "TM%dS2: pitch=%i, \n",
+                                                 word - 11,
+                                                 ((data[i] >> 21) + 1) * 4);
+                                       i++;
+                                       instr_out(ctx, i++,
+                                                 "TM%dS3\n", word - 11);
+                                       instr_out(ctx, i++,
+                                                 "TM%dS4: dflt color\n",
+                                                 word - 11);
+                               }
+                       }
+               }
+               if (len != i) {
+                       fprintf(out,
+                               "Bad count in 3DSTATE_LOAD_STATE_IMMEDIATE_2\n");
+               }
+               return len;
+       case 0x00:
+               instr_out(ctx, 0, "3DSTATE_MAP_STATE\n");
+               len = (data[0] & 0x0000003f) + 2;
+               instr_out(ctx, 1, "mask\n");
+
+               i = 2;
+               for (map = 0; map <= 15; map++) {
+                       if (data[1] & (1 << map)) {
+                               int width, height, pitch, dword;
+                               const char *tiling;
+
+                               dword = data[i];
+                               instr_out(ctx, i++,
+                                         "map %d MS2 %s%s%s\n", map,
+                                         dword & (1 << 31) ?
+                                         "untrusted surface, " : "",
+                                         dword & (1 << 1) ?
+                                         "vertical line stride enable, " : "",
+                                         dword & (1 << 0) ?
+                                         "vertical ofs enable, " : "");
+
+                               dword = data[i];
+                               width = ((dword >> 10) & ((1 << 11) - 1)) + 1;
+                               height = ((dword >> 21) & ((1 << 11) - 1)) + 1;
+
+                               tiling = "none";
+                               if (dword & (1 << 2))
+                                       tiling = "fenced";
+                               else if (dword & (1 << 1))
+                                       tiling = dword & (1 << 0) ? "Y" : "X";
+                               type = " BAD";
+                               format = "BAD";
+                               switch ((dword >> 7) & 0x7) {
+                               case 1:
+                                       type = "8b";
+                                       switch ((dword >> 3) & 0xf) {
+                                       case 0:
+                                               format = "I";
+                                               break;
+                                       case 1:
+                                               format = "L";
+                                               break;
+                                       case 4:
+                                               format = "A";
+                                               break;
+                                       case 5:
+                                               format = " mono";
+                                               break;
+                                       }
+                                       break;
+                               case 2:
+                                       type = "16b";
+                                       switch ((dword >> 3) & 0xf) {
+                                       case 0:
+                                               format = " rgb565";
+                                               break;
+                                       case 1:
+                                               format = " argb1555";
+                                               break;
+                                       case 2:
+                                               format = " argb4444";
+                                               break;
+                                       case 5:
+                                               format = " ay88";
+                                               break;
+                                       case 6:
+                                               format = " bump655";
+                                               break;
+                                       case 7:
+                                               format = "I";
+                                               break;
+                                       case 8:
+                                               format = "L";
+                                               break;
+                                       case 9:
+                                               format = "A";
+                                               break;
+                                       }
+                                       break;
+                               case 3:
+                                       type = "32b";
+                                       switch ((dword >> 3) & 0xf) {
+                                       case 0:
+                                               format = " argb8888";
+                                               break;
+                                       case 1:
+                                               format = " abgr8888";
+                                               break;
+                                       case 2:
+                                               format = " xrgb8888";
+                                               break;
+                                       case 3:
+                                               format = " xbgr8888";
+                                               break;
+                                       case 4:
+                                               format = " qwvu8888";
+                                               break;
+                                       case 5:
+                                               format = " axvu8888";
+                                               break;
+                                       case 6:
+                                               format = " lxvu8888";
+                                               break;
+                                       case 7:
+                                               format = " xlvu8888";
+                                               break;
+                                       case 8:
+                                               format = " argb2101010";
+                                               break;
+                                       case 9:
+                                               format = " abgr2101010";
+                                               break;
+                                       case 10:
+                                               format = " awvu2101010";
+                                               break;
+                                       case 11:
+                                               format = " gr1616";
+                                               break;
+                                       case 12:
+                                               format = " vu1616";
+                                               break;
+                                       case 13:
+                                               format = " xI824";
+                                               break;
+                                       case 14:
+                                               format = " xA824";
+                                               break;
+                                       case 15:
+                                               format = " xL824";
+                                               break;
+                                       }
+                                       break;
+                               case 5:
+                                       type = "422";
+                                       switch ((dword >> 3) & 0xf) {
+                                       case 0:
+                                               format = " yuv_swapy";
+                                               break;
+                                       case 1:
+                                               format = " yuv";
+                                               break;
+                                       case 2:
+                                               format = " yuv_swapuv";
+                                               break;
+                                       case 3:
+                                               format = " yuv_swapuvy";
+                                               break;
+                                       }
+                                       break;
+                               case 6:
+                                       type = "compressed";
+                                       switch ((dword >> 3) & 0x7) {
+                                       case 0:
+                                               format = " dxt1";
+                                               break;
+                                       case 1:
+                                               format = " dxt2_3";
+                                               break;
+                                       case 2:
+                                               format = " dxt4_5";
+                                               break;
+                                       case 3:
+                                               format = " fxt1";
+                                               break;
+                                       case 4:
+                                               format = " dxt1_rb";
+                                               break;
+                                       }
+                                       break;
+                               case 7:
+                                       type = "4b indexed";
+                                       switch ((dword >> 3) & 0xf) {
+                                       case 7:
+                                               format = " argb8888";
+                                               break;
+                                       }
+                                       break;
+                               }
+                               dword = data[i];
+                               instr_out(ctx, i++,
+                                         "map %d MS3 [width=%d, height=%d, format=%s%s, tiling=%s%s]\n",
+                                         map, width, height, type, format,
+                                         tiling,
+                                         dword & (1 << 9) ? " palette select" :
+                                         "");
+
+                               dword = data[i];
+                               pitch =
+                                   4 * (((dword >> 21) & ((1 << 11) - 1)) + 1);
+                               instr_out(ctx, i++,
+                                         "map %d MS4 [pitch=%d, max_lod=%i, vol_depth=%i, cube_face_ena=%x, %s]\n",
+                                         map, pitch, (dword >> 9) & 0x3f,
+                                         dword & 0xff, (dword >> 15) & 0x3f,
+                                         dword & (1 << 8) ? "miplayout legacy"
+                                         : "miplayout right");
+                       }
+               }
+               if (len != i) {
+                       fprintf(out, "Bad count in 3DSTATE_MAP_STATE\n");
+                       return len;
+               }
+               return len;
+       case 0x06:
+               instr_out(ctx, 0,
+                         "3DSTATE_PIXEL_SHADER_CONSTANTS\n");
+               len = (data[0] & 0x000000ff) + 2;
+
+               i = 2;
+               for (c = 0; c <= 31; c++) {
+                       if (data[1] & (1 << c)) {
+                               instr_out(ctx, i, "C%d.X = %f\n", c,
+                                         int_as_float(data[i]));
+                               i++;
+                               instr_out(ctx, i, "C%d.Y = %f\n",
+                                         c, int_as_float(data[i]));
+                               i++;
+                               instr_out(ctx, i, "C%d.Z = %f\n",
+                                         c, int_as_float(data[i]));
+                               i++;
+                               instr_out(ctx, i, "C%d.W = %f\n",
+                                         c, int_as_float(data[i]));
+                               i++;
+                       }
+               }
+               if (len != i) {
+                       fprintf(out,
+                               "Bad count in 3DSTATE_PIXEL_SHADER_CONSTANTS\n");
+               }
+               return len;
+       case 0x05:
+               instr_out(ctx, 0, "3DSTATE_PIXEL_SHADER_PROGRAM\n");
+               len = (data[0] & 0x000000ff) + 2;
+               if ((len - 1) % 3 != 0 || len > 370) {
+                       fprintf(out,
+                               "Bad count in 3DSTATE_PIXEL_SHADER_PROGRAM\n");
+               }
+               i = 1;
+               for (instr = 0; instr < (len - 1) / 3; instr++) {
+                       char instr_prefix[10];
+
+                       sprintf(instr_prefix, "PS%03d", instr);
+                       i915_decode_instruction(ctx, i,
+                                               instr_prefix);
+                       i += 3;
+               }
+               return len;
+       case 0x01:
+               if (IS_GEN2(devid))
+                       break;
+               instr_out(ctx, 0, "3DSTATE_SAMPLER_STATE\n");
+               instr_out(ctx, 1, "mask\n");
+               len = (data[0] & 0x0000003f) + 2;
+               i = 2;
+               for (sampler = 0; sampler <= 15; sampler++) {
+                       if (data[1] & (1 << sampler)) {
+                               uint32_t dword;
+                               const char *mip_filter = "";
+
+                               dword = data[i];
+                               switch ((dword >> 20) & 0x3) {
+                               case 0:
+                                       mip_filter = "none";
+                                       break;
+                               case 1:
+                                       mip_filter = "nearest";
+                                       break;
+                               case 3:
+                                       mip_filter = "linear";
+                                       break;
+                               }
+                               instr_out(ctx, i++,
+                                         "sampler %d SS2:%s%s%s "
+                                         "base_mip_level=%i, mip_filter=%s, mag_filter=%s, min_filter=%s "
+                                         "lod_bias=%.2f,%s max_aniso=%i, shadow_func=%s\n",
+                                         sampler,
+                                         dword & (1 << 31) ? " reverse gamma,"
+                                         : "",
+                                         dword & (1 << 30) ? " packed2planar,"
+                                         : "",
+                                         dword & (1 << 29) ?
+                                         " colorspace conversion," : "",
+                                         (dword >> 22) & 0x1f, mip_filter,
+                                         decode_sample_filter(dword >> 17),
+                                         decode_sample_filter(dword >> 14),
+                                         ((dword >> 5) & 0x1ff) / (0x10 * 1.0),
+                                         dword & (1 << 4) ? " shadow," : "",
+                                         dword & (1 << 3) ? 4 : 2,
+                                         decode_compare_func(dword));
+                               dword = data[i];
+                               instr_out(ctx, i++,
+                                         "sampler %d SS3: min_lod=%.2f,%s "
+                                         "tcmode_x=%s, tcmode_y=%s, tcmode_z=%s,%s texmap_idx=%i,%s\n",
+                                         sampler,
+                                         ((dword >> 24) & 0xff) / (0x10 * 1.0),
+                                         dword & (1 << 17) ?
+                                         " kill pixel enable," : "",
+                                         decode_tex_coord_mode(dword >> 12),
+                                         decode_tex_coord_mode(dword >> 9),
+                                         decode_tex_coord_mode(dword >> 6),
+                                         dword & (1 << 5) ?
+                                         " normalized coords," : "",
+                                         (dword >> 1) & 0xf,
+                                         dword & (1 << 0) ? " deinterlacer," :
+                                         "");
+                               dword = data[i];
+                               instr_out(ctx, i++,
+                                         "sampler %d SS4: border color\n",
+                                         sampler);
+                       }
+               }
+               if (len != i) {
+                       fprintf(out, "Bad count in 3DSTATE_SAMPLER_STATE\n");
+               }
+               return len;
+       case 0x85:
+               len = (data[0] & 0x0000000f) + 2;
+
+               if (len != 2)
+                       fprintf(out,
+                               "Bad count in 3DSTATE_DEST_BUFFER_VARIABLES\n");
+
+               instr_out(ctx, 0,
+                         "3DSTATE_DEST_BUFFER_VARIABLES\n");
+
+               switch ((data[1] >> 8) & 0xf) {
+               case 0x0:
+                       format = "g8";
+                       break;
+               case 0x1:
+                       format = "x1r5g5b5";
+                       break;
+               case 0x2:
+                       format = "r5g6b5";
+                       break;
+               case 0x3:
+                       format = "a8r8g8b8";
+                       break;
+               case 0x4:
+                       format = "ycrcb_swapy";
+                       break;
+               case 0x5:
+                       format = "ycrcb_normal";
+                       break;
+               case 0x6:
+                       format = "ycrcb_swapuv";
+                       break;
+               case 0x7:
+                       format = "ycrcb_swapuvy";
+                       break;
+               case 0x8:
+                       format = "a4r4g4b4";
+                       break;
+               case 0x9:
+                       format = "a1r5g5b5";
+                       break;
+               case 0xa:
+                       format = "a2r10g10b10";
+                       break;
+               default:
+                       format = "BAD";
+                       break;
+               }
+               switch ((data[1] >> 2) & 0x3) {
+               case 0x0:
+                       zformat = "u16";
+                       break;
+               case 0x1:
+                       zformat = "f16";
+                       break;
+               case 0x2:
+                       zformat = "u24x8";
+                       break;
+               default:
+                       zformat = "BAD";
+                       break;
+               }
+               instr_out(ctx, 1,
+                         "%s format, %s depth format, early Z %sabled\n",
+                         format, zformat,
+                         (data[1] & (1 << 31)) ? "en" : "dis");
+               return len;
+
+       case 0x8e:
+               {
+                       const char *name, *tiling;
+
+                       len = (data[0] & 0x0000000f) + 2;
+                       if (len != 3)
+                               fprintf(out,
+                                       "Bad count in 3DSTATE_BUFFER_INFO\n");
+
+                       switch ((data[1] >> 24) & 0x7) {
+                       case 0x3:
+                               name = "color";
+                               break;
+                       case 0x7:
+                               name = "depth";
+                               break;
+                       default:
+                               name = "unknown";
+                               break;
+                       }
+
+                       tiling = "none";
+                       if (data[1] & (1 << 23))
+                               tiling = "fenced";
+                       else if (data[1] & (1 << 22))
+                               tiling = data[1] & (1 << 21) ? "Y" : "X";
+
+                       instr_out(ctx, 0, "3DSTATE_BUFFER_INFO\n");
+                       instr_out(ctx, 1,
+                                 "%s, tiling = %s, pitch=%d\n", name, tiling,
+                                 data[1] & 0xffff);
+
+                       instr_out(ctx, 2, "address\n");
+                       return len;
+               }
+       case 0x81:
+               len = (data[0] & 0x0000000f) + 2;
+
+               if (len != 3)
+                       fprintf(out,
+                               "Bad count in 3DSTATE_SCISSOR_RECTANGLE\n");
+
+               instr_out(ctx, 0, "3DSTATE_SCISSOR_RECTANGLE\n");
+               instr_out(ctx, 1, "(%d,%d)\n",
+                         data[1] & 0xffff, data[1] >> 16);
+               instr_out(ctx, 2, "(%d,%d)\n",
+                         data[2] & 0xffff, data[2] >> 16);
+
+               return len;
+       case 0x80:
+               len = (data[0] & 0x0000000f) + 2;
+
+               if (len != 5)
+                       fprintf(out,
+                               "Bad count in 3DSTATE_DRAWING_RECTANGLE\n");
+
+               instr_out(ctx, 0, "3DSTATE_DRAWING_RECTANGLE\n");
+               instr_out(ctx, 1, "%s\n",
+                         data[1] & (1 << 30) ? "depth ofs disabled " : "");
+               instr_out(ctx, 2, "(%d,%d)\n",
+                         data[2] & 0xffff, data[2] >> 16);
+               instr_out(ctx, 3, "(%d,%d)\n",
+                         data[3] & 0xffff, data[3] >> 16);
+               instr_out(ctx, 4, "(%d,%d)\n",
+                         data[4] & 0xffff, data[4] >> 16);
+
+               return len;
+       case 0x9c:
+               len = (data[0] & 0x0000000f) + 2;
+
+               if (len != 7)
+                       fprintf(out, "Bad count in 3DSTATE_CLEAR_PARAMETERS\n");
+
+               instr_out(ctx, 0, "3DSTATE_CLEAR_PARAMETERS\n");
+               instr_out(ctx, 1, "prim_type=%s, clear=%s%s%s\n",
+                         data[1] & (1 << 16) ? "CLEAR_RECT" : "ZONE_INIT",
+                         data[1] & (1 << 2) ? "color," : "",
+                         data[1] & (1 << 1) ? "depth," : "",
+                         data[1] & (1 << 0) ? "stencil," : "");
+               instr_out(ctx, 2, "clear color\n");
+               instr_out(ctx, 3, "clear depth/stencil\n");
+               instr_out(ctx, 4, "color value (rgba8888)\n");
+               instr_out(ctx, 5, "depth value %f\n",
+                         int_as_float(data[5]));
+               instr_out(ctx, 6, "clear stencil\n");
+               return len;
+       }
+
+       for (idx = 0; idx < ARRAY_SIZE(opcodes_3d_1d); idx++) {
+               opcode_3d_1d = &opcodes_3d_1d[idx];
+               if (opcode_3d_1d->i830_only && !IS_GEN2(devid))
+                       continue;
+
+               if (((data[0] & 0x00ff0000) >> 16) == opcode_3d_1d->opcode) {
+                       len = 1;
+
+                       instr_out(ctx, 0, "%s\n",
+                                 opcode_3d_1d->name);
+                       if (opcode_3d_1d->max_len > 1) {
+                               len = (data[0] & 0x0000ffff) + 2;
+                               if (len < opcode_3d_1d->min_len ||
+                                   len > opcode_3d_1d->max_len) {
+                                       fprintf(out, "Bad count in %s\n",
+                                               opcode_3d_1d->name);
+                               }
+                       }
+
+                       for (i = 1; i < len; i++) {
+                               instr_out(ctx, i, "dword %d\n", i);
+                       }
+
+                       return len;
+               }
+       }
+
+       instr_out(ctx, 0, "3D UNKNOWN: 3d_1d opcode = 0x%x\n",
+                 opcode);
+       return 1;
+}
+
+static int
+decode_3d_primitive(struct drm_intel_decode *ctx)
+{
+       uint32_t *data = ctx->data;
+       uint32_t count = ctx->count;
+       char immediate = (data[0] & (1 << 23)) == 0;
+       unsigned int len, i, j, ret;
+       const char *primtype;
+       int original_s2 = saved_s2;
+       int original_s4 = saved_s4;
+
+       switch ((data[0] >> 18) & 0xf) {
+       case 0x0:
+               primtype = "TRILIST";
+               break;
+       case 0x1:
+               primtype = "TRISTRIP";
+               break;
+       case 0x2:
+               primtype = "TRISTRIP_REVERSE";
+               break;
+       case 0x3:
+               primtype = "TRIFAN";
+               break;
+       case 0x4:
+               primtype = "POLYGON";
+               break;
+       case 0x5:
+               primtype = "LINELIST";
+               break;
+       case 0x6:
+               primtype = "LINESTRIP";
+               break;
+       case 0x7:
+               primtype = "RECTLIST";
+               break;
+       case 0x8:
+               primtype = "POINTLIST";
+               break;
+       case 0x9:
+               primtype = "DIB";
+               break;
+       case 0xa:
+               primtype = "CLEAR_RECT";
+               saved_s4 = 3 << 6;
+               saved_s2 = ~0;
+               break;
+       default:
+               primtype = "unknown";
+               break;
+       }
+
+       /* XXX: 3DPRIM_DIB not supported */
+       if (immediate) {
+               len = (data[0] & 0x0003ffff) + 2;
+               instr_out(ctx, 0, "3DPRIMITIVE inline %s\n",
+                         primtype);
+               if (count < len)
+                       BUFFER_FAIL(count, len, "3DPRIMITIVE inline");
+               if (!saved_s2_set || !saved_s4_set) {
+                       fprintf(out, "unknown vertex format\n");
+                       for (i = 1; i < len; i++) {
+                               instr_out(ctx, i,
+                                         "           vertex data (%f float)\n",
+                                         int_as_float(data[i]));
+                       }
+               } else {
+                       unsigned int vertex = 0;
+                       for (i = 1; i < len;) {
+                               unsigned int tc;
+
+#define VERTEX_OUT(fmt, ...) do {                                      \
+    if (i < len)                                                       \
+       instr_out(ctx, i, " V%d."fmt"\n", vertex, __VA_ARGS__); \
+    else                                                               \
+       fprintf(out, " missing data in V%d\n", vertex);                 \
+    i++;                                                               \
+} while (0)
+
+                               VERTEX_OUT("X = %f", int_as_float(data[i]));
+                               VERTEX_OUT("Y = %f", int_as_float(data[i]));
+                               switch (saved_s4 >> 6 & 0x7) {
+                               case 0x1:
+                                       VERTEX_OUT("Z = %f",
+                                                  int_as_float(data[i]));
+                                       break;
+                               case 0x2:
+                                       VERTEX_OUT("Z = %f",
+                                                  int_as_float(data[i]));
+                                       VERTEX_OUT("W = %f",
+                                                  int_as_float(data[i]));
+                                       break;
+                               case 0x3:
+                                       break;
+                               case 0x4:
+                                       VERTEX_OUT("W = %f",
+                                                  int_as_float(data[i]));
+                                       break;
+                               default:
+                                       fprintf(out, "bad S4 position mask\n");
+                               }
+
+                               if (saved_s4 & (1 << 10)) {
+                                       VERTEX_OUT
+                                           ("color = (A=0x%02x, R=0x%02x, G=0x%02x, "
+                                            "B=0x%02x)", data[i] >> 24,
+                                            (data[i] >> 16) & 0xff,
+                                            (data[i] >> 8) & 0xff,
+                                            data[i] & 0xff);
+                               }
+                               if (saved_s4 & (1 << 11)) {
+                                       VERTEX_OUT
+                                           ("spec = (A=0x%02x, R=0x%02x, G=0x%02x, "
+                                            "B=0x%02x)", data[i] >> 24,
+                                            (data[i] >> 16) & 0xff,
+                                            (data[i] >> 8) & 0xff,
+                                            data[i] & 0xff);
+                               }
+                               if (saved_s4 & (1 << 12))
+                                       VERTEX_OUT("width = 0x%08x)", data[i]);
+
+                               for (tc = 0; tc <= 7; tc++) {
+                                       switch ((saved_s2 >> (tc * 4)) & 0xf) {
+                                       case 0x0:
+                                               VERTEX_OUT("T%d.X = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               VERTEX_OUT("T%d.Y = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               break;
+                                       case 0x1:
+                                               VERTEX_OUT("T%d.X = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               VERTEX_OUT("T%d.Y = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               VERTEX_OUT("T%d.Z = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               break;
+                                       case 0x2:
+                                               VERTEX_OUT("T%d.X = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               VERTEX_OUT("T%d.Y = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               VERTEX_OUT("T%d.Z = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               VERTEX_OUT("T%d.W = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               break;
+                                       case 0x3:
+                                               VERTEX_OUT("T%d.X = %f", tc,
+                                                          int_as_float(data
+                                                                       [i]));
+                                               break;
+                                       case 0x4:
+                                               VERTEX_OUT
+                                                   ("T%d.XY = 0x%08x half-float",
+                                                    tc, data[i]);
+                                               break;
+                                       case 0x5:
+                                               VERTEX_OUT
+                                                   ("T%d.XY = 0x%08x half-float",
+                                                    tc, data[i]);
+                                               VERTEX_OUT
+                                                   ("T%d.ZW = 0x%08x half-float",
+                                                    tc, data[i]);
+                                               break;
+                                       case 0xf:
+                                               break;
+                                       default:
+                                               fprintf(out,
+                                                       "bad S2.T%d format\n",
+                                                       tc);
+                                       }
+                               }
+                               vertex++;
+                       }
+               }
+
+               ret = len;
+       } else {
+               /* indirect vertices */
+               len = data[0] & 0x0000ffff;     /* index count */
+               if (data[0] & (1 << 17)) {
+                       /* random vertex access */
+                       if (count < (len + 1) / 2 + 1) {
+                               BUFFER_FAIL(count, (len + 1) / 2 + 1,
+                                           "3DPRIMITIVE random indirect");
+                       }
+                       instr_out(ctx, 0,
+                                 "3DPRIMITIVE random indirect %s (%d)\n",
+                                 primtype, len);
+                       if (len == 0) {
+                               /* vertex indices continue until 0xffff is
+                                * found
+                                */
+                               for (i = 1; i < count; i++) {
+                                       if ((data[i] & 0xffff) == 0xffff) {
+                                               instr_out(ctx, i,
+                                                         "    indices: (terminator)\n");
+                                               ret = i;
+                                               goto out;
+                                       } else if ((data[i] >> 16) == 0xffff) {
+                                               instr_out(ctx, i,
+                                                         "    indices: 0x%04x, (terminator)\n",
+                                                         data[i] & 0xffff);
+                                               ret = i;
+                                               goto out;
+                                       } else {
+                                               instr_out(ctx, i,
+                                                         "    indices: 0x%04x, 0x%04x\n",
+                                                         data[i] & 0xffff,
+                                                         data[i] >> 16);
+                                       }
+                               }
+                               fprintf(out,
+                                       "3DPRIMITIVE: no terminator found in index buffer\n");
+                               ret = count;
+                               goto out;
+                       } else {
+                               /* fixed size vertex index buffer */
+                               for (j = 1, i = 0; i < len; i += 2, j++) {
+                                       if (i * 2 == len - 1) {
+                                               instr_out(ctx, j,
+                                                         "    indices: 0x%04x\n",
+                                                         data[j] & 0xffff);
+                                       } else {
+                                               instr_out(ctx, j,
+                                                         "    indices: 0x%04x, 0x%04x\n",
+                                                         data[j] & 0xffff,
+                                                         data[j] >> 16);
+                                       }
+                               }
+                       }
+                       ret = (len + 1) / 2 + 1;
+                       goto out;
+               } else {
+                       /* sequential vertex access */
+                       instr_out(ctx, 0,
+                                 "3DPRIMITIVE sequential indirect %s, %d starting from "
+                                 "%d\n", primtype, len, data[1] & 0xffff);
+                       instr_out(ctx, 1, "           start\n");
+                       ret = 2;
+                       goto out;
+               }
+       }
+
+out:
+       saved_s2 = original_s2;
+       saved_s4 = original_s4;
+       return ret;
+}
+
+static int
+decode_3d(struct drm_intel_decode *ctx)
+{
+       uint32_t opcode;
+       unsigned int idx;
+       uint32_t *data = ctx->data;
+
+       struct {
+               uint32_t opcode;
+               unsigned int min_len;
+               unsigned int max_len;
+               const char *name;
+       } opcodes_3d[] = {
+               { 0x06, 1, 1, "3DSTATE_ANTI_ALIASING" },
+               { 0x08, 1, 1, "3DSTATE_BACKFACE_STENCIL_OPS" },
+               { 0x09, 1, 1, "3DSTATE_BACKFACE_STENCIL_MASKS" },
+               { 0x16, 1, 1, "3DSTATE_COORD_SET_BINDINGS" },
+               { 0x15, 1, 1, "3DSTATE_FOG_COLOR" },
+               { 0x0b, 1, 1, "3DSTATE_INDEPENDENT_ALPHA_BLEND" },
+               { 0x0d, 1, 1, "3DSTATE_MODES_4" },
+               { 0x0c, 1, 1, "3DSTATE_MODES_5" },
+               { 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES"},
+       }, *opcode_3d;
+
+       opcode = (data[0] & 0x1f000000) >> 24;
+
+       switch (opcode) {
+       case 0x1f:
+               return decode_3d_primitive(ctx);
+       case 0x1d:
+               return decode_3d_1d(ctx);
+       case 0x1c:
+               return decode_3d_1c(ctx);
+       }
+
+       for (idx = 0; idx < ARRAY_SIZE(opcodes_3d); idx++) {
+               opcode_3d = &opcodes_3d[idx];
+               if (opcode == opcode_3d->opcode) {
+                       unsigned int len = 1, i;
+
+                       instr_out(ctx, 0, "%s\n", opcode_3d->name);
+                       if (opcode_3d->max_len > 1) {
+                               len = (data[0] & 0xff) + 2;
+                               if (len < opcode_3d->min_len ||
+                                   len > opcode_3d->max_len) {
+                                       fprintf(out, "Bad count in %s\n",
+                                               opcode_3d->name);
+                               }
+                       }
+
+                       for (i = 1; i < len; i++) {
+                               instr_out(ctx, i, "dword %d\n", i);
+                       }
+                       return len;
+               }
+       }
+
+       instr_out(ctx, 0, "3D UNKNOWN: 3d opcode = 0x%x\n", opcode);
+       return 1;
+}
+
+static const char *get_965_surfacetype(unsigned int surfacetype)
+{
+       switch (surfacetype) {
+       case 0:
+               return "1D";
+       case 1:
+               return "2D";
+       case 2:
+               return "3D";
+       case 3:
+               return "CUBE";
+       case 4:
+               return "BUFFER";
+       case 7:
+               return "NULL";
+       default:
+               return "unknown";
+       }
+}
+
+static const char *get_965_depthformat(unsigned int depthformat)
+{
+       switch (depthformat) {
+       case 0:
+               return "s8_z24float";
+       case 1:
+               return "z32float";
+       case 2:
+               return "z24s8";
+       case 5:
+               return "z16";
+       default:
+               return "unknown";
+       }
+}
+
+static const char *get_965_element_component(uint32_t data, int component)
+{
+       uint32_t component_control = (data >> (16 + (3 - component) * 4)) & 0x7;
+
+       switch (component_control) {
+       case 0:
+               return "nostore";
+       case 1:
+               switch (component) {
+               case 0:
+                       return "X";
+               case 1:
+                       return "Y";
+               case 2:
+                       return "Z";
+               case 3:
+                       return "W";
+               default:
+                       return "fail";
+               }
+       case 2:
+               return "0.0";
+       case 3:
+               return "1.0";
+       case 4:
+               return "0x1";
+       case 5:
+               return "VID";
+       default:
+               return "fail";
+       }
+}
+
+static const char *get_965_prim_type(uint32_t primtype)
+{
+       switch (primtype) {
+       case 0x01:
+               return "point list";
+       case 0x02:
+               return "line list";
+       case 0x03:
+               return "line strip";
+       case 0x04:
+               return "tri list";
+       case 0x05:
+               return "tri strip";
+       case 0x06:
+               return "tri fan";
+       case 0x07:
+               return "quad list";
+       case 0x08:
+               return "quad strip";
+       case 0x09:
+               return "line list adj";
+       case 0x0a:
+               return "line strip adj";
+       case 0x0b:
+               return "tri list adj";
+       case 0x0c:
+               return "tri strip adj";
+       case 0x0d:
+               return "tri strip reverse";
+       case 0x0e:
+               return "polygon";
+       case 0x0f:
+               return "rect list";
+       case 0x10:
+               return "line loop";
+       case 0x11:
+               return "point list bf";
+       case 0x12:
+               return "line strip cont";
+       case 0x13:
+               return "line strip bf";
+       case 0x14:
+               return "line strip cont bf";
+       case 0x15:
+               return "tri fan no stipple";
+       default:
+               return "fail";
+       }
+}
+
+static int
+i965_decode_urb_fence(struct drm_intel_decode *ctx, int len)
+{
+       uint32_t vs_fence, clip_fence, gs_fence, sf_fence, vfe_fence, cs_fence;
+       uint32_t *data = ctx->data;
+
+       if (len != 3)
+               fprintf(out, "Bad count in URB_FENCE\n");
+
+       vs_fence = data[1] & 0x3ff;
+       gs_fence = (data[1] >> 10) & 0x3ff;
+       clip_fence = (data[1] >> 20) & 0x3ff;
+       sf_fence = data[2] & 0x3ff;
+       vfe_fence = (data[2] >> 10) & 0x3ff;
+       cs_fence = (data[2] >> 20) & 0x7ff;
+
+       instr_out(ctx, 0, "URB_FENCE: %s%s%s%s%s%s\n",
+                 (data[0] >> 13) & 1 ? "cs " : "",
+                 (data[0] >> 12) & 1 ? "vfe " : "",
+                 (data[0] >> 11) & 1 ? "sf " : "",
+                 (data[0] >> 10) & 1 ? "clip " : "",
+                 (data[0] >> 9) & 1 ? "gs " : "",
+                 (data[0] >> 8) & 1 ? "vs " : "");
+       instr_out(ctx, 1,
+                 "vs fence: %d, clip_fence: %d, gs_fence: %d\n",
+                 vs_fence, clip_fence, gs_fence);
+       instr_out(ctx, 2,
+                 "sf fence: %d, vfe_fence: %d, cs_fence: %d\n",
+                 sf_fence, vfe_fence, cs_fence);
+       if (gs_fence < vs_fence)
+               fprintf(out, "gs fence < vs fence!\n");
+       if (clip_fence < gs_fence)
+               fprintf(out, "clip fence < gs fence!\n");
+       if (sf_fence < clip_fence)
+               fprintf(out, "sf fence < clip fence!\n");
+       if (cs_fence < sf_fence)
+               fprintf(out, "cs fence < sf fence!\n");
+
+       return len;
+}
+
+static void
+state_base_out(struct drm_intel_decode *ctx, unsigned int index,
+              const char *name)
+{
+       if (ctx->data[index] & 1) {
+               instr_out(ctx, index,
+                         "%s state base address 0x%08x\n", name,
+                         ctx->data[index] & ~1);
+       } else {
+               instr_out(ctx, index, "%s state base not updated\n",
+                         name);
+       }
+}
+
+static void
+state_max_out(struct drm_intel_decode *ctx, unsigned int index,
+             const char *name)
+{
+       if (ctx->data[index] & 1) {
+               if (ctx->data[index] == 1) {
+                       instr_out(ctx, index,
+                                 "%s state upper bound disabled\n", name);
+               } else {
+                       instr_out(ctx, index,
+                                 "%s state upper bound 0x%08x\n", name,
+                                 ctx->data[index] & ~1);
+               }
+       } else {
+               instr_out(ctx, index,
+                         "%s state upper bound not updated\n", name);
+       }
+}
+
+static int
+gen7_3DSTATE_VIEWPORT_STATE_POINTERS_CC(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_VIEWPORT_STATE_POINTERS_CC\n");
+       instr_out(ctx, 1, "pointer to CC viewport\n");
+
+       return 2;
+}
+
+static int
+gen7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP\n");
+       instr_out(ctx, 1, "pointer to SF_CLIP viewport\n");
+
+       return 2;
+}
+
+static int
+gen7_3DSTATE_BLEND_STATE_POINTERS(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_BLEND_STATE_POINTERS\n");
+       instr_out(ctx, 1, "pointer to BLEND_STATE at 0x%08x (%s)\n",
+                 ctx->data[1] & ~1,
+                 (ctx->data[1] & 1) ? "changed" : "unchanged");
+
+       return 2;
+}
+
+static int
+gen7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_DEPTH_STENCIL_STATE_POINTERS\n");
+       instr_out(ctx, 1,
+                 "pointer to DEPTH_STENCIL_STATE at 0x%08x (%s)\n",
+                 ctx->data[1] & ~1,
+                 (ctx->data[1] & 1) ? "changed" : "unchanged");
+
+       return 2;
+}
+
+static int
+gen7_3DSTATE_HIER_DEPTH_BUFFER(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_HIER_DEPTH_BUFFER\n");
+       instr_out(ctx, 1, "pitch %db\n",
+                 (ctx->data[1] & 0x1ffff) + 1);
+       instr_out(ctx, 2, "pointer to HiZ buffer\n");
+
+       return 3;
+}
+
+static int
+gen6_3DSTATE_CC_STATE_POINTERS(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_CC_STATE_POINTERS\n");
+       instr_out(ctx, 1, "blend change %d\n", ctx->data[1] & 1);
+       instr_out(ctx, 2, "depth stencil change %d\n",
+                 ctx->data[2] & 1);
+       instr_out(ctx, 3, "cc change %d\n", ctx->data[3] & 1);
+
+       return 4;
+}
+
+static int
+gen7_3DSTATE_CC_STATE_POINTERS(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_CC_STATE_POINTERS\n");
+       instr_out(ctx, 1, "pointer to COLOR_CALC_STATE at 0x%08x "
+                 "(%s)\n",
+                 ctx->data[1] & ~1,
+                 (ctx->data[1] & 1) ? "changed" : "unchanged");
+
+       return 2;
+}
+
+static int
+gen7_3DSTATE_URB_unit(struct drm_intel_decode *ctx, const char *unit)
+{
+    int start_kb = ((ctx->data[1] >> 25) & 0x3f) * 8;
+    /* the field is # of 512-bit rows - 1, we print bytes */
+    int entry_size = (((ctx->data[1] >> 16) & 0x1ff) + 1);
+    int nr_entries = ctx->data[1] & 0xffff;
+
+    instr_out(ctx, 0, "3DSTATE_URB_%s\n", unit);
+    instr_out(ctx, 1,
+             "%dKB start, size=%d 64B rows, nr_entries=%d, total size %dB\n",
+             start_kb, entry_size, nr_entries, nr_entries * 64 * entry_size);
+
+    return 2;
+}
+
+static int
+gen7_3DSTATE_URB_VS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_URB_unit(ctx, "VS");
+}
+
+static int
+gen7_3DSTATE_URB_HS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_URB_unit(ctx, "HS");
+}
+
+static int
+gen7_3DSTATE_URB_DS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_URB_unit(ctx, "DS");
+}
+
+static int
+gen7_3DSTATE_URB_GS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_URB_unit(ctx, "GS");
+}
+
+static int
+gen7_3DSTATE_CONSTANT(struct drm_intel_decode *ctx, const char *unit)
+{
+       int rlen[4];
+
+       rlen[0] = (ctx->data[1] >> 0) & 0xffff;
+       rlen[1] = (ctx->data[1] >> 16) & 0xffff;
+       rlen[2] = (ctx->data[2] >> 0) & 0xffff;
+       rlen[3] = (ctx->data[2] >> 16) & 0xffff;
+
+       instr_out(ctx, 0, "3DSTATE_CONSTANT_%s\n", unit);
+       instr_out(ctx, 1, "len 0 = %d, len 1 = %d\n", rlen[0], rlen[1]);
+       instr_out(ctx, 2, "len 2 = %d, len 3 = %d\n", rlen[2], rlen[3]);
+       instr_out(ctx, 3, "pointer to constbuf 0\n");
+       instr_out(ctx, 4, "pointer to constbuf 1\n");
+       instr_out(ctx, 5, "pointer to constbuf 2\n");
+       instr_out(ctx, 6, "pointer to constbuf 3\n");
+
+       return 7;
+}
+
+static int
+gen7_3DSTATE_CONSTANT_VS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_CONSTANT(ctx, "VS");
+}
+
+static int
+gen7_3DSTATE_CONSTANT_GS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_CONSTANT(ctx, "GS");
+}
+
+static int
+gen7_3DSTATE_CONSTANT_PS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_CONSTANT(ctx, "PS");
+}
+
+static int
+gen7_3DSTATE_CONSTANT_DS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_CONSTANT(ctx, "DS");
+}
+
+static int
+gen7_3DSTATE_CONSTANT_HS(struct drm_intel_decode *ctx)
+{
+       return gen7_3DSTATE_CONSTANT(ctx, "HS");
+}
+
+
+static int
+gen6_3DSTATE_WM(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0, "3DSTATE_WM\n");
+       instr_out(ctx, 1, "kernel start pointer 0\n");
+       instr_out(ctx, 2,
+                 "SPF=%d, VME=%d, Sampler Count %d, "
+                 "Binding table count %d\n",
+                 (ctx->data[2] >> 31) & 1,
+                 (ctx->data[2] >> 30) & 1,
+                 (ctx->data[2] >> 27) & 7,
+                 (ctx->data[2] >> 18) & 0xff);
+       instr_out(ctx, 3, "scratch offset\n");
+       instr_out(ctx, 4,
+                 "Depth Clear %d, Depth Resolve %d, HiZ Resolve %d, "
+                 "Dispatch GRF start[0] %d, start[1] %d, start[2] %d\n",
+                 (ctx->data[4] & (1 << 30)) != 0,
+                 (ctx->data[4] & (1 << 28)) != 0,
+                 (ctx->data[4] & (1 << 27)) != 0,
+                 (ctx->data[4] >> 16) & 0x7f,
+                 (ctx->data[4] >> 8) & 0x7f,
+                 (ctx->data[4] & 0x7f));
+       instr_out(ctx, 5,
+                 "MaxThreads %d, PS KillPixel %d, PS computed Z %d, "
+                 "PS use sourceZ %d, Thread Dispatch %d, PS use sourceW %d, "
+                 "Dispatch32 %d, Dispatch16 %d, Dispatch8 %d\n",
+                 ((ctx->data[5] >> 25) & 0x7f) + 1,
+                 (ctx->data[5] & (1 << 22)) != 0,
+                 (ctx->data[5] & (1 << 21)) != 0,
+                 (ctx->data[5] & (1 << 20)) != 0,
+                 (ctx->data[5] & (1 << 19)) != 0,
+                 (ctx->data[5] & (1 << 8)) != 0,
+                 (ctx->data[5] & (1 << 2)) != 0,
+                 (ctx->data[5] & (1 << 1)) != 0,
+                 (ctx->data[5] & (1 << 0)) != 0);
+       instr_out(ctx, 6,
+                 "Num SF output %d, Pos XY offset %d, ZW interp mode %d , "
+                 "Barycentric interp mode 0x%x, Point raster rule %d, "
+                 "Multisample mode %d, "
+                 "Multisample Dispatch mode %d\n",
+                 (ctx->data[6] >> 20) & 0x3f,
+                 (ctx->data[6] >> 18) & 3,
+                 (ctx->data[6] >> 16) & 3,
+                 (ctx->data[6] >> 10) & 0x3f,
+                 (ctx->data[6] & (1 << 9)) != 0,
+                 (ctx->data[6] >> 1) & 3,
+                 (ctx->data[6] & 1));
+       instr_out(ctx, 7, "kernel start pointer 1\n");
+       instr_out(ctx, 8, "kernel start pointer 2\n");
+
+       return 9;
+}
+
+static int
+gen7_3DSTATE_WM(struct drm_intel_decode *ctx)
+{
+       const char *computed_depth = "";
+       const char *early_depth = "";
+       const char *zw_interp = "";
+
+       switch ((ctx->data[1] >> 23) & 0x3) {
+       case 0:
+               computed_depth = "";
+               break;
+       case 1:
+               computed_depth = "computed depth";
+               break;
+       case 2:
+               computed_depth = "computed depth >=";
+               break;
+       case 3:
+               computed_depth = "computed depth <=";
+               break;
+       }
+
+       switch ((ctx->data[1] >> 21) & 0x3) {
+       case 0:
+               early_depth = "";
+               break;
+       case 1:
+               early_depth = ", EDSC_PSEXEC";
+               break;
+       case 2:
+               early_depth = ", EDSC_PREPS";
+               break;
+       case 3:
+               early_depth = ", BAD EDSC";
+               break;
+       }
+
+       switch ((ctx->data[1] >> 17) & 0x3) {
+       case 0:
+               early_depth = "";
+               break;
+       case 1:
+               early_depth = ", BAD ZW interp";
+               break;
+       case 2:
+               early_depth = ", ZW centroid";
+               break;
+       case 3:
+               early_depth = ", ZW sample";
+               break;
+       }
+
+       instr_out(ctx, 0, "3DSTATE_WM\n");
+       instr_out(ctx, 1, "(%s%s%s%s%s%s)%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+                 (ctx->data[1] & (1 << 11)) ? "PP " : "",
+                 (ctx->data[1] & (1 << 12)) ? "PC " : "",
+                 (ctx->data[1] & (1 << 13)) ? "PS " : "",
+                 (ctx->data[1] & (1 << 14)) ? "NPP " : "",
+                 (ctx->data[1] & (1 << 15)) ? "NPC " : "",
+                 (ctx->data[1] & (1 << 16)) ? "NPS " : "",
+                 (ctx->data[1] & (1 << 30)) ? ", depth clear" : "",
+                 (ctx->data[1] & (1 << 29)) ? "" : ", disabled",
+                 (ctx->data[1] & (1 << 28)) ? ", depth resolve" : "",
+                 (ctx->data[1] & (1 << 27)) ? ", hiz resolve" : "",
+                 (ctx->data[1] & (1 << 25)) ? ", kill" : "",
+                 computed_depth,
+                 early_depth,
+                 zw_interp,
+                 (ctx->data[1] & (1 << 20)) ? ", source depth" : "",
+                 (ctx->data[1] & (1 << 19)) ? ", source W" : "",
+                 (ctx->data[1] & (1 << 10)) ? ", coverage" : "",
+                 (ctx->data[1] & (1 << 4)) ? ", poly stipple" : "",
+                 (ctx->data[1] & (1 << 3)) ? ", line stipple" : "",
+                 (ctx->data[1] & (1 << 2)) ? ", point UL" : ", point UR"
+                 );
+       instr_out(ctx, 2, "MS\n");
+
+       return 3;
+}
+
+static int
+gen4_3DPRIMITIVE(struct drm_intel_decode *ctx)
+{
+       instr_out(ctx, 0,
+                 "3DPRIMITIVE: %s %s\n",
+                 get_965_prim_type((ctx->data[0] >> 10) & 0x1f),
+                 (ctx->data[0] & (1 << 15)) ? "random" : "sequential");
+       instr_out(ctx, 1, "vertex count\n");
+       instr_out(ctx, 2, "start vertex\n");
+       instr_out(ctx, 3, "instance count\n");
+       instr_out(ctx, 4, "start instance\n");
+       instr_out(ctx, 5, "index bias\n");
+
+       return 6;
+}
+
+static int
+gen7_3DPRIMITIVE(struct drm_intel_decode *ctx)
+{
+       bool indirect = !!(ctx->data[0] & (1 << 10));
+
+       instr_out(ctx, 0,
+                 "3DPRIMITIVE: %s%s\n",
+                 indirect ? " indirect" : "",
+                 (ctx->data[0] & (1 << 8)) ? " predicated" : "");
+       instr_out(ctx, 1, "%s %s\n",
+                 get_965_prim_type(ctx->data[1] & 0x3f),
+                 (ctx->data[1] & (1 << 8)) ? "random" : "sequential");
+       instr_out(ctx, 2, indirect ? "ignored" : "vertex count\n");
+       instr_out(ctx, 3, indirect ? "ignored" : "start vertex\n");
+       instr_out(ctx, 4, indirect ? "ignored" : "instance count\n");
+       instr_out(ctx, 5, indirect ? "ignored" : "start instance\n");
+       instr_out(ctx, 6, indirect ? "ignored" : "index bias\n");
+
+       return 7;
+}
+
+static int
+decode_3d_965(struct drm_intel_decode *ctx)
+{
+       uint32_t opcode;
+       unsigned int len;
+       unsigned int i, j, sba_len;
+       const char *desc1 = NULL;
+       uint32_t *data = ctx->data;
+       uint32_t devid = ctx->devid;
+
+       struct {
+               uint32_t opcode;
+               uint32_t len_mask;
+               int unsigned min_len;
+               int unsigned max_len;
+               const char *name;
+               int gen;
+               int (*func)(struct drm_intel_decode *ctx);
+       } opcodes_3d[] = {
+               { 0x6000, 0x00ff, 3, 3, "URB_FENCE" },
+               { 0x6001, 0xffff, 2, 2, "CS_URB_STATE" },
+               { 0x6002, 0x00ff, 2, 2, "CONSTANT_BUFFER" },
+               { 0x6101, 0xffff, 6, 10, "STATE_BASE_ADDRESS" },
+               { 0x6102, 0xffff, 2, 2, "STATE_SIP" },
+               { 0x6104, 0xffff, 1, 1, "3DSTATE_PIPELINE_SELECT" },
+               { 0x680b, 0xffff, 1, 1, "3DSTATE_VF_STATISTICS" },
+               { 0x6904, 0xffff, 1, 1, "3DSTATE_PIPELINE_SELECT" },
+               { 0x7800, 0xffff, 7, 7, "3DSTATE_PIPELINED_POINTERS" },
+               { 0x7801, 0x00ff, 4, 6, "3DSTATE_BINDING_TABLE_POINTERS" },
+               { 0x7802, 0x00ff, 4, 4, "3DSTATE_SAMPLER_STATE_POINTERS" },
+               { 0x7805, 0x00ff, 7, 7, "3DSTATE_DEPTH_BUFFER", 7 },
+               { 0x7805, 0x00ff, 3, 3, "3DSTATE_URB" },
+               { 0x7804, 0x00ff, 3, 3, "3DSTATE_CLEAR_PARAMS" },
+               { 0x7806, 0x00ff, 3, 3, "3DSTATE_STENCIL_BUFFER" },
+               { 0x7807, 0x00ff, 4, 4, "3DSTATE_HIER_DEPTH_BUFFER", 6 },
+               { 0x7807, 0x00ff, 3, 3, "3DSTATE_HIER_DEPTH_BUFFER", 7, gen7_3DSTATE_HIER_DEPTH_BUFFER },
+               { 0x7808, 0x00ff, 5, 257, "3DSTATE_VERTEX_BUFFERS" },
+               { 0x7809, 0x00ff, 3, 256, "3DSTATE_VERTEX_ELEMENTS" },
+               { 0x780a, 0x00ff, 3, 3, "3DSTATE_INDEX_BUFFER" },
+               { 0x780b, 0xffff, 1, 1, "3DSTATE_VF_STATISTICS" },
+               { 0x780d, 0x00ff, 4, 4, "3DSTATE_VIEWPORT_STATE_POINTERS" },
+               { 0x780e, 0xffff, 4, 4, NULL, 6, gen6_3DSTATE_CC_STATE_POINTERS },
+               { 0x780e, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_CC_STATE_POINTERS },
+               { 0x780f, 0x00ff, 2, 2, "3DSTATE_SCISSOR_POINTERS" },
+               { 0x7810, 0x00ff, 6, 6, "3DSTATE_VS" },
+               { 0x7811, 0x00ff, 7, 7, "3DSTATE_GS" },
+               { 0x7812, 0x00ff, 4, 4, "3DSTATE_CLIP" },
+               { 0x7813, 0x00ff, 20, 20, "3DSTATE_SF", 6 },
+               { 0x7813, 0x00ff, 7, 7, "3DSTATE_SF", 7 },
+               { 0x7814, 0x00ff, 3, 3, "3DSTATE_WM", 7, gen7_3DSTATE_WM },
+               { 0x7814, 0x00ff, 9, 9, "3DSTATE_WM", 6, gen6_3DSTATE_WM },
+               { 0x7815, 0x00ff, 5, 5, "3DSTATE_CONSTANT_VS_STATE", 6 },
+               { 0x7815, 0x00ff, 7, 7, "3DSTATE_CONSTANT_VS", 7, gen7_3DSTATE_CONSTANT_VS },
+               { 0x7816, 0x00ff, 5, 5, "3DSTATE_CONSTANT_GS_STATE", 6 },
+               { 0x7816, 0x00ff, 7, 7, "3DSTATE_CONSTANT_GS", 7, gen7_3DSTATE_CONSTANT_GS },
+               { 0x7817, 0x00ff, 5, 5, "3DSTATE_CONSTANT_PS_STATE", 6 },
+               { 0x7817, 0x00ff, 7, 7, "3DSTATE_CONSTANT_PS", 7, gen7_3DSTATE_CONSTANT_PS },
+               { 0x7818, 0xffff, 2, 2, "3DSTATE_SAMPLE_MASK" },
+               { 0x7819, 0x00ff, 7, 7, "3DSTATE_CONSTANT_HS", 7, gen7_3DSTATE_CONSTANT_HS },
+               { 0x781a, 0x00ff, 7, 7, "3DSTATE_CONSTANT_DS", 7, gen7_3DSTATE_CONSTANT_DS },
+               { 0x781b, 0x00ff, 7, 7, "3DSTATE_HS" },
+               { 0x781c, 0x00ff, 4, 4, "3DSTATE_TE" },
+               { 0x781d, 0x00ff, 6, 6, "3DSTATE_DS" },
+               { 0x781e, 0x00ff, 3, 3, "3DSTATE_STREAMOUT" },
+               { 0x781f, 0x00ff, 14, 14, "3DSTATE_SBE" },
+               { 0x7820, 0x00ff, 8, 8, "3DSTATE_PS" },
+               { 0x7821, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP },
+               { 0x7823, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_VIEWPORT_STATE_POINTERS_CC },
+               { 0x7824, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_BLEND_STATE_POINTERS },
+               { 0x7825, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_DEPTH_STENCIL_STATE_POINTERS },
+               { 0x7826, 0x00ff, 2, 2, "3DSTATE_BINDING_TABLE_POINTERS_VS" },
+               { 0x7827, 0x00ff, 2, 2, "3DSTATE_BINDING_TABLE_POINTERS_HS" },
+               { 0x7828, 0x00ff, 2, 2, "3DSTATE_BINDING_TABLE_POINTERS_DS" },
+               { 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" },
+               { 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 },
+               { 0x7831, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_URB_HS },
+               { 0x7832, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_URB_DS },
+               { 0x7833, 0x00ff, 2, 2, NULL, 7, gen7_3DSTATE_URB_GS },
+               { 0x7900, 0xffff, 4, 4, "3DSTATE_DRAWING_RECTANGLE" },
+               { 0x7901, 0xffff, 5, 5, "3DSTATE_CONSTANT_COLOR" },
+               { 0x7905, 0xffff, 5, 7, "3DSTATE_DEPTH_BUFFER" },
+               { 0x7906, 0xffff, 2, 2, "3DSTATE_POLY_STIPPLE_OFFSET" },
+               { 0x7907, 0xffff, 33, 33, "3DSTATE_POLY_STIPPLE_PATTERN" },
+               { 0x7908, 0xffff, 3, 3, "3DSTATE_LINE_STIPPLE" },
+               { 0x7909, 0xffff, 2, 2, "3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP" },
+               { 0x7909, 0xffff, 2, 2, "3DSTATE_CLEAR_PARAMS" },
+               { 0x790a, 0xffff, 3, 3, "3DSTATE_AA_LINE_PARAMETERS" },
+               { 0x790b, 0xffff, 4, 4, "3DSTATE_GS_SVB_INDEX" },
+               { 0x790d, 0xffff, 3, 3, "3DSTATE_MULTISAMPLE", 6 },
+               { 0x790d, 0xffff, 4, 4, "3DSTATE_MULTISAMPLE", 7 },
+               { 0x7910, 0xffff, 2, 2, "3DSTATE_CLEAR_PARAMS" },
+               { 0x7912, 0x00ff, 2, 2, "3DSTATE_PUSH_CONSTANT_ALLOC_VS" },
+               { 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" },
+               { 0x7a00, 0x00ff, 4, 6, "PIPE_CONTROL" },
+               { 0x7b00, 0x00ff, 7, 7, NULL, 7, gen7_3DPRIMITIVE },
+               { 0x7b00, 0x00ff, 6, 6, NULL, 0, gen4_3DPRIMITIVE },
+       }, *opcode_3d = NULL;
+
+       opcode = (data[0] & 0xffff0000) >> 16;
+
+       for (i = 0; i < ARRAY_SIZE(opcodes_3d); i++) {
+               if (opcode != opcodes_3d[i].opcode)
+                       continue;
+
+               /* If it's marked as not our gen, skip. */
+               if (opcodes_3d[i].gen && opcodes_3d[i].gen != ctx->gen)
+                       continue;
+
+               opcode_3d = &opcodes_3d[i];
+               break;
+       }
+
+       if (opcode_3d) {
+               if (opcode_3d->max_len == 1)
+                       len = 1;
+               else
+                       len = (data[0] & opcode_3d->len_mask) + 2;
+
+               if (len < opcode_3d->min_len ||
+                   len > opcode_3d->max_len) {
+                       fprintf(out, "Bad length %d in %s, expected %d-%d\n",
+                               len, opcode_3d->name,
+                               opcode_3d->min_len, opcode_3d->max_len);
+               }
+       } else {
+               len = (data[0] & 0x0000ffff) + 2;
+       }
+
+       switch (opcode) {
+       case 0x6000:
+               return i965_decode_urb_fence(ctx, len);
+       case 0x6001:
+               instr_out(ctx, 0, "CS_URB_STATE\n");
+               instr_out(ctx, 1,
+                         "entry_size: %d [%d bytes], n_entries: %d\n",
+                         (data[1] >> 4) & 0x1f,
+                         (((data[1] >> 4) & 0x1f) + 1) * 64, data[1] & 0x7);
+               return len;
+       case 0x6002:
+               instr_out(ctx, 0, "CONSTANT_BUFFER: %s\n",
+                         (data[0] >> 8) & 1 ? "valid" : "invalid");
+               instr_out(ctx, 1,
+                         "offset: 0x%08x, length: %d bytes\n", data[1] & ~0x3f,
+                         ((data[1] & 0x3f) + 1) * 64);
+               return len;
+       case 0x6101:
+               i = 0;
+               instr_out(ctx, 0, "STATE_BASE_ADDRESS\n");
+               i++;
+
+               if (IS_GEN6(devid) || IS_GEN7(devid))
+                       sba_len = 10;
+               else if (IS_GEN5(devid))
+                       sba_len = 8;
+               else
+                       sba_len = 6;
+               if (len != sba_len)
+                       fprintf(out, "Bad count in STATE_BASE_ADDRESS\n");
+
+               state_base_out(ctx, i++, "general");
+               state_base_out(ctx, i++, "surface");
+               if (IS_GEN6(devid) || IS_GEN7(devid))
+                       state_base_out(ctx, i++, "dynamic");
+               state_base_out(ctx, i++, "indirect");
+               if (IS_GEN5(devid) || IS_GEN6(devid) || IS_GEN7(devid))
+                       state_base_out(ctx, i++, "instruction");
+
+               state_max_out(ctx, i++, "general");
+               if (IS_GEN6(devid) || IS_GEN7(devid))
+                       state_max_out(ctx, i++, "dynamic");
+               state_max_out(ctx, i++, "indirect");
+               if (IS_GEN5(devid) || IS_GEN6(devid) || IS_GEN7(devid))
+                       state_max_out(ctx, i++, "instruction");
+
+               return len;
+       case 0x7800:
+               instr_out(ctx, 0, "3DSTATE_PIPELINED_POINTERS\n");
+               instr_out(ctx, 1, "VS state\n");
+               instr_out(ctx, 2, "GS state\n");
+               instr_out(ctx, 3, "Clip state\n");
+               instr_out(ctx, 4, "SF state\n");
+               instr_out(ctx, 5, "WM state\n");
+               instr_out(ctx, 6, "CC state\n");
+               return len;
+       case 0x7801:
+               if (len != 6 && len != 4)
+                       fprintf(out,
+                               "Bad count in 3DSTATE_BINDING_TABLE_POINTERS\n");
+               if (len == 6) {
+                       instr_out(ctx, 0,
+                                 "3DSTATE_BINDING_TABLE_POINTERS\n");
+                       instr_out(ctx, 1, "VS binding table\n");
+                       instr_out(ctx, 2, "GS binding table\n");
+                       instr_out(ctx, 3, "Clip binding table\n");
+                       instr_out(ctx, 4, "SF binding table\n");
+                       instr_out(ctx, 5, "WM binding table\n");
+               } else {
+                       instr_out(ctx, 0,
+                                 "3DSTATE_BINDING_TABLE_POINTERS: VS mod %d, "
+                                 "GS mod %d, PS mod %d\n",
+                                 (data[0] & (1 << 8)) != 0,
+                                 (data[0] & (1 << 9)) != 0,
+                                 (data[0] & (1 << 12)) != 0);
+                       instr_out(ctx, 1, "VS binding table\n");
+                       instr_out(ctx, 2, "GS binding table\n");
+                       instr_out(ctx, 3, "WM binding table\n");
+               }
+
+               return len;
+       case 0x7802:
+               instr_out(ctx, 0,
+                         "3DSTATE_SAMPLER_STATE_POINTERS: VS mod %d, "
+                         "GS mod %d, PS mod %d\n", (data[0] & (1 << 8)) != 0,
+                         (data[0] & (1 << 9)) != 0,
+                         (data[0] & (1 << 12)) != 0);
+               instr_out(ctx, 1, "VS sampler state\n");
+               instr_out(ctx, 2, "GS sampler state\n");
+               instr_out(ctx, 3, "WM sampler state\n");
+               return len;
+       case 0x7805:
+               /* Actually 3DSTATE_DEPTH_BUFFER on gen7. */
+               if (ctx->gen == 7)
+                       break;
+
+               instr_out(ctx, 0, "3DSTATE_URB\n");
+               instr_out(ctx, 1,
+                         "VS entries %d, alloc size %d (1024bit row)\n",
+                         data[1] & 0xffff, ((data[1] >> 16) & 0x07f) + 1);
+               instr_out(ctx, 2,
+                         "GS entries %d, alloc size %d (1024bit row)\n",
+                         (data[2] >> 8) & 0x3ff, (data[2] & 7) + 1);
+               return len;
+
+       case 0x7808:
+               if ((len - 1) % 4 != 0)
+                       fprintf(out, "Bad count in 3DSTATE_VERTEX_BUFFERS\n");
+               instr_out(ctx, 0, "3DSTATE_VERTEX_BUFFERS\n");
+
+               for (i = 1; i < len;) {
+                       int idx, access;
+                       if (IS_GEN6(devid)) {
+                               idx = 26;
+                               access = 20;
+                       } else {
+                               idx = 27;
+                               access = 26;
+                       }
+                       instr_out(ctx, i,
+                                 "buffer %d: %s, pitch %db\n", data[i] >> idx,
+                                 data[i] & (1 << access) ? "random" :
+                                 "sequential", data[i] & 0x07ff);
+                       i++;
+                       instr_out(ctx, i++, "buffer address\n");
+                       instr_out(ctx, i++, "max index\n");
+                       instr_out(ctx, i++, "mbz\n");
+               }
+               return len;
+
+       case 0x7809:
+               if ((len + 1) % 2 != 0)
+                       fprintf(out, "Bad count in 3DSTATE_VERTEX_ELEMENTS\n");
+               instr_out(ctx, 0, "3DSTATE_VERTEX_ELEMENTS\n");
+
+               for (i = 1; i < len;) {
+                       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)) ?
+                                 "" : "in", (data[i] >> 16) & 0x1ff,
+                                 data[i] & 0x07ff);
+                       i++;
+                       instr_out(ctx, i, "(%s, %s, %s, %s), "
+                                 "dst offset 0x%02x bytes\n",
+                                 get_965_element_component(data[i], 0),
+                                 get_965_element_component(data[i], 1),
+                                 get_965_element_component(data[i], 2),
+                                 get_965_element_component(data[i], 3),
+                                 (data[i] & 0xff) * 4);
+                       i++;
+               }
+               return len;
+
+       case 0x780d:
+               instr_out(ctx, 0,
+                         "3DSTATE_VIEWPORT_STATE_POINTERS\n");
+               instr_out(ctx, 1, "clip\n");
+               instr_out(ctx, 2, "sf\n");
+               instr_out(ctx, 3, "cc\n");
+               return len;
+
+       case 0x780a:
+               instr_out(ctx, 0, "3DSTATE_INDEX_BUFFER\n");
+               instr_out(ctx, 1, "beginning buffer address\n");
+               instr_out(ctx, 2, "ending buffer address\n");
+               return len;
+
+       case 0x780f:
+               instr_out(ctx, 0, "3DSTATE_SCISSOR_POINTERS\n");
+               instr_out(ctx, 1, "scissor rect offset\n");
+               return len;
+
+       case 0x7810:
+               instr_out(ctx, 0, "3DSTATE_VS\n");
+               instr_out(ctx, 1, "kernel pointer\n");
+               instr_out(ctx, 2,
+                         "SPF=%d, VME=%d, Sampler Count %d, "
+                         "Binding table count %d\n", (data[2] >> 31) & 1,
+                         (data[2] >> 30) & 1, (data[2] >> 27) & 7,
+                         (data[2] >> 18) & 0xff);
+               instr_out(ctx, 3, "scratch offset\n");
+               instr_out(ctx, 4,
+                         "Dispatch GRF start %d, VUE read length %d, "
+                         "VUE read offset %d\n", (data[4] >> 20) & 0x1f,
+                         (data[4] >> 11) & 0x3f, (data[4] >> 4) & 0x3f);
+               instr_out(ctx, 5,
+                         "Max Threads %d, Vertex Cache %sable, "
+                         "VS func %sable\n", ((data[5] >> 25) & 0x7f) + 1,
+                         (data[5] & (1 << 1)) != 0 ? "dis" : "en",
+                         (data[5] & 1) != 0 ? "en" : "dis");
+               return len;
+
+       case 0x7811:
+               instr_out(ctx, 0, "3DSTATE_GS\n");
+               instr_out(ctx, 1, "kernel pointer\n");
+               instr_out(ctx, 2,
+                         "SPF=%d, VME=%d, Sampler Count %d, "
+                         "Binding table count %d\n", (data[2] >> 31) & 1,
+                         (data[2] >> 30) & 1, (data[2] >> 27) & 7,
+                         (data[2] >> 18) & 0xff);
+               instr_out(ctx, 3, "scratch offset\n");
+               instr_out(ctx, 4,
+                         "Dispatch GRF start %d, VUE read length %d, "
+                         "VUE read offset %d\n", (data[4] & 0xf),
+                         (data[4] >> 11) & 0x3f, (data[4] >> 4) & 0x3f);
+               instr_out(ctx, 5,
+                         "Max Threads %d, Rendering %sable\n",
+                         ((data[5] >> 25) & 0x7f) + 1,
+                         (data[5] & (1 << 8)) != 0 ? "en" : "dis");
+               instr_out(ctx, 6,
+                         "Reorder %sable, Discard Adjaceny %sable, "
+                         "GS %sable\n",
+                         (data[6] & (1 << 30)) != 0 ? "en" : "dis",
+                         (data[6] & (1 << 29)) != 0 ? "en" : "dis",
+                         (data[6] & (1 << 15)) != 0 ? "en" : "dis");
+               return len;
+
+       case 0x7812:
+               instr_out(ctx, 0, "3DSTATE_CLIP\n");
+               instr_out(ctx, 1,
+                         "UserClip distance cull test mask 0x%x\n",
+                         data[1] & 0xff);
+               instr_out(ctx, 2,
+                         "Clip %sable, API mode %s, Viewport XY test %sable, "
+                         "Viewport Z test %sable, Guardband test %sable, Clip mode %d, "
+                         "Perspective Divide %sable, Non-Perspective Barycentric %sable, "
+                         "Tri Provoking %d, Line Provoking %d, Trifan Provoking %d\n",
+                         (data[2] & (1 << 31)) != 0 ? "en" : "dis",
+                         (data[2] & (1 << 30)) != 0 ? "D3D" : "OGL",
+                         (data[2] & (1 << 28)) != 0 ? "en" : "dis",
+                         (data[2] & (1 << 27)) != 0 ? "en" : "dis",
+                         (data[2] & (1 << 26)) != 0 ? "en" : "dis",
+                         (data[2] >> 13) & 7,
+                         (data[2] & (1 << 9)) != 0 ? "dis" : "en",
+                         (data[2] & (1 << 8)) != 0 ? "en" : "dis",
+                         (data[2] >> 4) & 3, (data[2] >> 2) & 3,
+                         (data[2] & 3));
+               instr_out(ctx, 3,
+                         "Min PointWidth %d, Max PointWidth %d, "
+                         "Force Zero RTAIndex %sable, Max VPIndex %d\n",
+                         (data[3] >> 17) & 0x7ff, (data[3] >> 6) & 0x7ff,
+                         (data[3] & (1 << 5)) != 0 ? "en" : "dis",
+                         (data[3] & 0xf));
+               return len;
+
+       case 0x7813:
+               if (ctx->gen == 7)
+                       break;
+
+               instr_out(ctx, 0, "3DSTATE_SF\n");
+               instr_out(ctx, 1,
+                         "Attrib Out %d, Attrib Swizzle %sable, VUE read length %d, "
+                         "VUE read offset %d\n", (data[1] >> 22) & 0x3f,
+                         (data[1] & (1 << 21)) != 0 ? "en" : "dis",
+                         (data[1] >> 11) & 0x1f, (data[1] >> 4) & 0x3f);
+               instr_out(ctx, 2,
+                         "Legacy Global DepthBias %sable, FrontFace fill %d, BF fill %d, "
+                         "VP transform %sable, FrontWinding_%s\n",
+                         (data[2] & (1 << 11)) != 0 ? "en" : "dis",
+                         (data[2] >> 5) & 3, (data[2] >> 3) & 3,
+                         (data[2] & (1 << 1)) != 0 ? "en" : "dis",
+                         (data[2] & 1) != 0 ? "CCW" : "CW");
+               instr_out(ctx, 3,
+                         "AA %sable, CullMode %d, Scissor %sable, Multisample m ode %d\n",
+                         (data[3] & (1 << 31)) != 0 ? "en" : "dis",
+                         (data[3] >> 29) & 3,
+                         (data[3] & (1 << 11)) != 0 ? "en" : "dis",
+                         (data[3] >> 8) & 3);
+               instr_out(ctx, 4,
+                         "Last Pixel %sable, SubPixel Precision %d, Use PixelWidth %d\n",
+                         (data[4] & (1 << 31)) != 0 ? "en" : "dis",
+                         (data[4] & (1 << 12)) != 0 ? 4 : 8,
+                         (data[4] & (1 << 11)) != 0);
+               instr_out(ctx, 5,
+                         "Global Depth Offset Constant %f\n",
+                         *(float *)(&data[5]));
+               instr_out(ctx, 6, "Global Depth Offset Scale %f\n",
+                         *(float *)(&data[6]));
+               instr_out(ctx, 7, "Global Depth Offset Clamp %f\n",
+                         *(float *)(&data[7]));
+
+               for (i = 0, j = 0; i < 8; i++, j += 2)
+                       instr_out(ctx, i + 8,
+                                 "Attrib %d (Override %s%s%s%s, Const Source %d, Swizzle Select %d, "
+                                 "Source %d); Attrib %d (Override %s%s%s%s, Const Source %d, Swizzle Select %d, Source %d)\n",
+                                 j + 1,
+                                 (data[8 + i] & (1 << 31)) != 0 ? "W" : "",
+                                 (data[8 + i] & (1 << 30)) != 0 ? "Z" : "",
+                                 (data[8 + i] & (1 << 29)) != 0 ? "Y" : "",
+                                 (data[8 + i] & (1 << 28)) != 0 ? "X" : "",
+                                 (data[8 + i] >> 25) & 3,
+                                 (data[8 + i] >> 22) & 3,
+                                 (data[8 + i] >> 16) & 0x1f, j,
+                                 (data[8 + i] & (1 << 15)) != 0 ? "W" : "",
+                                 (data[8 + i] & (1 << 14)) != 0 ? "Z" : "",
+                                 (data[8 + i] & (1 << 13)) != 0 ? "Y" : "",
+                                 (data[8 + i] & (1 << 12)) != 0 ? "X" : "",
+                                 (data[8 + i] >> 9) & 3,
+                                 (data[8 + i] >> 6) & 3, (data[8 + i] & 0x1f));
+               instr_out(ctx, 16,
+                         "Point Sprite TexCoord Enable\n");
+               instr_out(ctx, 17, "Const Interp Enable\n");
+               instr_out(ctx, 18,
+                         "Attrib 7-0 WrapShortest Enable\n");
+               instr_out(ctx, 19,
+                         "Attrib 15-8 WrapShortest Enable\n");
+
+               return len;
+
+       case 0x7900:
+               instr_out(ctx, 0, "3DSTATE_DRAWING_RECTANGLE\n");
+               instr_out(ctx, 1, "top left: %d,%d\n",
+                         data[1] & 0xffff, (data[1] >> 16) & 0xffff);
+               instr_out(ctx, 2, "bottom right: %d,%d\n",
+                         data[2] & 0xffff, (data[2] >> 16) & 0xffff);
+               instr_out(ctx, 3, "origin: %d,%d\n",
+                         (int)data[3] & 0xffff, ((int)data[3] >> 16) & 0xffff);
+
+               return len;
+
+       case 0x7905:
+               instr_out(ctx, 0, "3DSTATE_DEPTH_BUFFER\n");
+               if (IS_GEN5(devid) || IS_GEN6(devid))
+                       instr_out(ctx, 1,
+                                 "%s, %s, pitch = %d bytes, %stiled, HiZ %d, Seperate Stencil %d\n",
+                                 get_965_surfacetype(data[1] >> 29),
+                                 get_965_depthformat((data[1] >> 18) & 0x7),
+                                 (data[1] & 0x0001ffff) + 1,
+                                 data[1] & (1 << 27) ? "" : "not ",
+                                 (data[1] & (1 << 22)) != 0,
+                                 (data[1] & (1 << 21)) != 0);
+               else
+                       instr_out(ctx, 1,
+                                 "%s, %s, pitch = %d bytes, %stiled\n",
+                                 get_965_surfacetype(data[1] >> 29),
+                                 get_965_depthformat((data[1] >> 18) & 0x7),
+                                 (data[1] & 0x0001ffff) + 1,
+                                 data[1] & (1 << 27) ? "" : "not ");
+               instr_out(ctx, 2, "depth offset\n");
+               instr_out(ctx, 3, "%dx%d\n",
+                         ((data[3] & 0x0007ffc0) >> 6) + 1,
+                         ((data[3] & 0xfff80000) >> 19) + 1);
+               instr_out(ctx, 4, "volume depth\n");
+               if (len >= 6)
+                       instr_out(ctx, 5, "\n");
+               if (len >= 7) {
+                       if (IS_GEN6(devid))
+                               instr_out(ctx, 6, "\n");
+                       else
+                               instr_out(ctx, 6,
+                                         "render target view extent\n");
+               }
+
+               return len;
+
+       case 0x7a00:
+               if (IS_GEN6(devid) || IS_GEN7(devid)) {
+                       unsigned int i;
+                       if (len != 4 && len != 5)
+                               fprintf(out, "Bad count in PIPE_CONTROL\n");
+
+                       switch ((data[1] >> 14) & 0x3) {
+                       case 0:
+                               desc1 = "no write";
+                               break;
+                       case 1:
+                               desc1 = "qword write";
+                               break;
+                       case 2:
+                               desc1 = "PS_DEPTH_COUNT write";
+                               break;
+                       case 3:
+                               desc1 = "TIMESTAMP write";
+                               break;
+                       }
+                       instr_out(ctx, 0, "PIPE_CONTROL\n");
+                       instr_out(ctx, 1,
+                                 "%s, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n",
+                                 desc1,
+                                 data[1] & (1 << 20) ? "cs stall, " : "",
+                                 data[1] & (1 << 19) ?
+                                 "global snapshot count reset, " : "",
+                                 data[1] & (1 << 18) ? "tlb invalidate, " : "",
+                                 data[1] & (1 << 17) ? "gfdt flush, " : "",
+                                 data[1] & (1 << 17) ? "media state clear, " :
+                                 "",
+                                 data[1] & (1 << 13) ? "depth stall, " : "",
+                                 data[1] & (1 << 12) ?
+                                 "render target cache flush, " : "",
+                                 data[1] & (1 << 11) ?
+                                 "instruction cache invalidate, " : "",
+                                 data[1] & (1 << 10) ?
+                                 "texture cache invalidate, " : "",
+                                 data[1] & (1 << 9) ?
+                                 "indirect state invalidate, " : "",
+                                 data[1] & (1 << 8) ? "notify irq, " : "",
+                                 data[1] & (1 << 7) ? "PIPE_CONTROL flush, " :
+                                 "",
+                                 data[1] & (1 << 6) ? "protect mem app_id, " :
+                                 "", data[1] & (1 << 5) ? "DC flush, " : "",
+                                 data[1] & (1 << 4) ? "vf fetch invalidate, " :
+                                 "",
+                                 data[1] & (1 << 3) ?
+                                 "constant cache invalidate, " : "",
+                                 data[1] & (1 << 2) ?
+                                 "state cache invalidate, " : "",
+                                 data[1] & (1 << 1) ? "stall at scoreboard, " :
+                                 "",
+                                 data[1] & (1 << 0) ? "depth cache flush, " :
+                                 "");
+                       if (len == 5) {
+                               instr_out(ctx, 2,
+                                         "destination address\n");
+                               instr_out(ctx, 3,
+                                         "immediate dword low\n");
+                               instr_out(ctx, 4,
+                                         "immediate dword high\n");
+                       } else {
+                               for (i = 2; i < len; i++) {
+                                       instr_out(ctx, i, "\n");
+                               }
+                       }
+                       return len;
+               } else {
+                       if (len != 4)
+                               fprintf(out, "Bad count in PIPE_CONTROL\n");
+
+                       switch ((data[0] >> 14) & 0x3) {
+                       case 0:
+                               desc1 = "no write";
+                               break;
+                       case 1:
+                               desc1 = "qword write";
+                               break;
+                       case 2:
+                               desc1 = "PS_DEPTH_COUNT write";
+                               break;
+                       case 3:
+                               desc1 = "TIMESTAMP write";
+                               break;
+                       }
+                       instr_out(ctx, 0,
+                                 "PIPE_CONTROL: %s, %sdepth stall, %sRC write flush, "
+                                 "%sinst flush\n",
+                                 desc1,
+                                 data[0] & (1 << 13) ? "" : "no ",
+                                 data[0] & (1 << 12) ? "" : "no ",
+                                 data[0] & (1 << 11) ? "" : "no ");
+                       instr_out(ctx, 1, "destination address\n");
+                       instr_out(ctx, 2, "immediate dword low\n");
+                       instr_out(ctx, 3, "immediate dword high\n");
+                       return len;
+               }
+       }
+
+       if (opcode_3d) {
+               if (opcode_3d->func) {
+                       return opcode_3d->func(ctx);
+               } else {
+                       unsigned int i;
+
+                       instr_out(ctx, 0, "%s\n", opcode_3d->name);
+
+                       for (i = 1; i < len; i++) {
+                               instr_out(ctx, i, "dword %d\n", i);
+                       }
+                       return len;
+               }
+       }
+
+       instr_out(ctx, 0, "3D UNKNOWN: 3d_965 opcode = 0x%x\n",
+                 opcode);
+       return 1;
+}
+
+static int
+decode_3d_i830(struct drm_intel_decode *ctx)
+{
+       unsigned int idx;
+       uint32_t opcode;
+       uint32_t *data = ctx->data;
+
+       struct {
+               uint32_t opcode;
+               unsigned int min_len;
+               unsigned int max_len;
+               const char *name;
+       } opcodes_3d[] = {
+               { 0x02, 1, 1, "3DSTATE_MODES_3" },
+               { 0x03, 1, 1, "3DSTATE_ENABLES_1" },
+               { 0x04, 1, 1, "3DSTATE_ENABLES_2" },
+               { 0x05, 1, 1, "3DSTATE_VFT0" },
+               { 0x06, 1, 1, "3DSTATE_AA" },
+               { 0x07, 1, 1, "3DSTATE_RASTERIZATION_RULES" },
+               { 0x08, 1, 1, "3DSTATE_MODES_1" },
+               { 0x09, 1, 1, "3DSTATE_STENCIL_TEST" },
+               { 0x0a, 1, 1, "3DSTATE_VFT1" },
+               { 0x0b, 1, 1, "3DSTATE_INDPT_ALPHA_BLEND" },
+               { 0x0c, 1, 1, "3DSTATE_MODES_5" },
+               { 0x0d, 1, 1, "3DSTATE_MAP_BLEND_OP" },
+               { 0x0e, 1, 1, "3DSTATE_MAP_BLEND_ARG" },
+               { 0x0f, 1, 1, "3DSTATE_MODES_2" },
+               { 0x15, 1, 1, "3DSTATE_FOG_COLOR" },
+               { 0x16, 1, 1, "3DSTATE_MODES_4"},
+       }, *opcode_3d;
+
+       opcode = (data[0] & 0x1f000000) >> 24;
+
+       switch (opcode) {
+       case 0x1f:
+               return decode_3d_primitive(ctx);
+       case 0x1d:
+               return decode_3d_1d(ctx);
+       case 0x1c:
+               return decode_3d_1c(ctx);
+       }
+
+       for (idx = 0; idx < ARRAY_SIZE(opcodes_3d); idx++) {
+               opcode_3d = &opcodes_3d[idx];
+               if ((data[0] & 0x1f000000) >> 24 == opcode_3d->opcode) {
+                       unsigned int len = 1, i;
+
+                       instr_out(ctx, 0, "%s\n", opcode_3d->name);
+                       if (opcode_3d->max_len > 1) {
+                               len = (data[0] & 0xff) + 2;
+                               if (len < opcode_3d->min_len ||
+                                   len > opcode_3d->max_len) {
+                                       fprintf(out, "Bad count in %s\n",
+                                               opcode_3d->name);
+                               }
+                       }
+
+                       for (i = 1; i < len; i++) {
+                               instr_out(ctx, i, "dword %d\n", i);
+                       }
+                       return len;
+               }
+       }
+
+       instr_out(ctx, 0, "3D UNKNOWN: 3d_i830 opcode = 0x%x\n",
+                 opcode);
+       return 1;
+}
+
+struct drm_intel_decode *
+drm_intel_decode_context_alloc(uint32_t devid)
+{
+       struct drm_intel_decode *ctx;
+
+       ctx = calloc(1, sizeof(struct drm_intel_decode));
+       if (!ctx)
+               return NULL;
+
+       ctx->devid = devid;
+       ctx->out = stdout;
+
+       if (IS_GEN7(devid))
+               ctx->gen = 7;
+       else if (IS_GEN6(devid))
+               ctx->gen = 6;
+       else if (IS_GEN5(devid))
+               ctx->gen = 5;
+       else if (IS_GEN4(devid))
+               ctx->gen = 4;
+       else if (IS_9XX(devid))
+               ctx->gen = 3;
+       else {
+               assert(IS_GEN2(devid));
+               ctx->gen = 2;
+       }
+
+       return ctx;
+}
+
+void
+drm_intel_decode_context_free(struct drm_intel_decode *ctx)
+{
+       free(ctx);
+}
+
+void
+drm_intel_decode_set_dump_past_end(struct drm_intel_decode *ctx,
+                                  int dump_past_end)
+{
+       ctx->dump_past_end = !!dump_past_end;
+}
+
+void
+drm_intel_decode_set_batch_pointer(struct drm_intel_decode *ctx,
+                                  void *data, uint32_t hw_offset, int count)
+{
+       ctx->base_data = data;
+       ctx->base_hw_offset = hw_offset;
+       ctx->base_count = count;
+}
+
+void
+drm_intel_decode_set_head_tail(struct drm_intel_decode *ctx,
+                              uint32_t head, uint32_t tail)
+{
+       ctx->head = head;
+       ctx->tail = tail;
+}
+
+void
+drm_intel_decode_set_output_file(struct drm_intel_decode *ctx,
+                                FILE *out)
+{
+       ctx->out = out;
+}
+
+/**
+ * Decodes an i830-i915 batch buffer, writing the output to stdout.
+ *
+ * \param data batch buffer contents
+ * \param count number of DWORDs to decode in the batch buffer
+ * \param hw_offset hardware address for the buffer
+ */
+void
+drm_intel_decode(struct drm_intel_decode *ctx)
+{
+       int ret;
+       unsigned int index = 0;
+       uint32_t devid;
+       int size = ctx->base_count * 4;
+       void *temp;
+
+       if (!ctx)
+               return;
+
+       /* Put a scratch page full of obviously undefined data after
+        * the batchbuffer.  This lets us avoid a bunch of length
+        * checking in statically sized packets.
+        */
+       temp = malloc(size + 4096);
+       memcpy(temp, ctx->base_data, size);
+       memset((char *)temp + size, 0xd0, 4096);
+       ctx->data = temp;
+
+       ctx->hw_offset = ctx->base_hw_offset;
+       ctx->count = ctx->base_count;
+
+       devid = ctx->devid;
+       head_offset = ctx->head;
+       tail_offset = ctx->tail;
+       out = ctx->out;
+
+       saved_s2_set = 0;
+       saved_s4_set = 1;
+
+       while (ctx->count > 0) {
+               index = 0;
+
+               switch ((ctx->data[index] & 0xe0000000) >> 29) {
+               case 0x0:
+                       ret = decode_mi(ctx);
+
+                       /* If MI_BATCHBUFFER_END happened, then dump
+                        * the rest of the output in case we some day
+                        * want it in debugging, but don't decode it
+                        * since it'll just confuse in the common
+                        * case.
+                        */
+                       if (ret == -1) {
+                               if (ctx->dump_past_end) {
+                                       index++;
+                               } else {
+                                       for (index = index + 1; index < ctx->count;
+                                            index++) {
+                                               instr_out(ctx, index, "\n");
+                                       }
+                               }
+                       } else
+                               index += ret;
+                       break;
+               case 0x2:
+                       index += decode_2d(ctx);
+                       break;
+               case 0x3:
+                       if (IS_9XX(devid) && !IS_GEN3(devid)) {
+                               index +=
+                                   decode_3d_965(ctx);
+                       } else if (IS_GEN3(devid)) {
+                               index += decode_3d(ctx);
+                       } else {
+                               index +=
+                                   decode_3d_i830(ctx);
+                       }
+                       break;
+               default:
+                       instr_out(ctx, index, "UNKNOWN\n");
+                       index++;
+                       break;
+               }
+               fflush(out);
+
+               if (ctx->count < index)
+                       break;
+
+               ctx->count -= index;
+               ctx->data += index;
+               ctx->hw_offset += 4 * index;
+       }
+
+       free(temp);
+}
diff --git a/intel/test_decode.c b/intel/test_decode.c
new file mode 100644 (file)
index 0000000..c9ab7ad
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ * Copyright Â© 2011 Intel Corporation
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <err.h>
+
+#include "config.h"
+#include "intel_bufmgr.h"
+#include "intel_chipset.h"
+
+#define HW_OFFSET 0x12300000
+
+static void
+usage(void)
+{
+       fprintf(stderr, "usage:\n");
+       fprintf(stderr, "  test_decode <batch>\n");
+       fprintf(stderr, "  test_decode <batch> -dump\n");
+       exit(1);
+}
+
+static void
+read_file(const char *filename, void **ptr, size_t *size)
+{
+       int fd, ret;
+       struct stat st;
+
+       fd = open(filename, O_RDONLY);
+       if (fd == -1)
+               errx(1, "couldn't open `%s'", filename);
+
+       ret = fstat(fd, &st);
+       if (ret)
+               errx(1, "couldn't stat `%s'", filename);
+
+       *size = st.st_size;
+       *ptr = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+       if (*ptr == MAP_FAILED)
+               errx(1, "couldn't map `%s'", filename);
+
+       close(fd);
+}
+
+static void
+dump_batch(struct drm_intel_decode *ctx, const char *batch_filename)
+{
+       void *batch_ptr;
+       size_t batch_size;
+
+       read_file(batch_filename, &batch_ptr, &batch_size);
+
+       drm_intel_decode_set_batch_pointer(ctx, batch_ptr, HW_OFFSET,
+                                          batch_size / 4);
+       drm_intel_decode_set_output_file(ctx, stdout);
+
+       drm_intel_decode(ctx);
+}
+
+static void
+compare_batch(struct drm_intel_decode *ctx, const char *batch_filename)
+{
+       FILE *out = NULL;
+       void *ptr, *ref_ptr, *batch_ptr;
+       size_t size, ref_size, batch_size;
+       const char *ref_suffix = "-ref.txt";
+       char *ref_filename;
+
+       ref_filename = malloc(strlen(batch_filename) + strlen(ref_suffix) + 1);
+       sprintf(ref_filename, "%s%s", batch_filename, ref_suffix);
+
+       /* Read the batch and reference. */
+       read_file(batch_filename, &batch_ptr, &batch_size);
+       read_file(ref_filename, &ref_ptr, &ref_size);
+
+       /* Set up our decode output in memory, because I don't want to
+        * figure out how to output to a file in a safe and sane way
+        * inside of an automake project's test infrastructure.
+        */
+#ifdef HAVE_OPEN_MEMSTREAM
+       out = open_memstream((char **)&ptr, &size);
+#else
+       fprintf(stderr, "platform lacks open_memstream, skipping.\n");
+       exit(77);
+#endif
+
+       drm_intel_decode_set_batch_pointer(ctx, batch_ptr, HW_OFFSET,
+                                          batch_size / 4);
+       drm_intel_decode_set_output_file(ctx, out);
+
+       drm_intel_decode(ctx);
+
+       if (strcmp(ref_ptr, ptr) != 0) {
+               fprintf(stderr, "Decode mismatch with reference `%s'.\n",
+                       ref_filename);
+               fprintf(stderr, "You can dump the new output using:\n");
+               fprintf(stderr, "  test_decode \"%s\" -dump\n", batch_filename);
+               exit(1);
+       }
+
+       fclose(out);
+       free(ref_filename);
+       free(ptr);
+}
+
+static uint16_t
+infer_devid(const char *batch_filename)
+{
+       struct {
+               const char *name;
+               uint16_t devid;
+       } chipsets[] = {
+               { "830",  0x3577},
+               { "855",  0x3582},
+               { "945",  0x2772},
+               { "gen4", 0x2a02 },
+               { "gm45", 0x2a42 },
+               { "gen5", PCI_CHIP_ILD_G },
+               { "gen6", PCI_CHIP_SANDYBRIDGE_GT2 },
+               { "gen7", PCI_CHIP_IVYBRIDGE_GT2 },
+               { NULL, 0 },
+       };
+       int i;
+
+       for (i = 0; chipsets[i].name != NULL; i++) {
+               if (strstr(batch_filename, chipsets[i].name))
+                       return chipsets[i].devid;
+       }
+
+       fprintf(stderr, "Couldn't guess chipset id from batch filename `%s'.\n",
+               batch_filename);
+       fprintf(stderr, "Must be contain one of:\n");
+       for (i = 0; chipsets[i].name != NULL; i++) {
+               fprintf(stderr, "  %s\n", chipsets[i].name);
+       }
+       exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+       uint16_t devid;
+       struct drm_intel_decode *ctx;
+
+       if (argc < 2)
+               usage();
+
+
+       devid = infer_devid(argv[1]);
+
+       ctx = drm_intel_decode_context_alloc(devid);
+
+       if (argc == 3) {
+               if (strcmp(argv[2], "-dump") == 0)
+                       dump_batch(ctx, argv[1]);
+               else
+                       usage();
+       } else {
+               compare_batch(ctx, argv[1]);
+       }
+
+       drm_intel_decode_context_free(ctx);
+
+       return 0;
+}
diff --git a/intel/tests/.gitignore b/intel/tests/.gitignore
new file mode 100644 (file)
index 0000000..e9d01ec
--- /dev/null
@@ -0,0 +1 @@
+*-new.txt
diff --git a/intel/tests/gen4-3d.batch b/intel/tests/gen4-3d.batch
new file mode 100644 (file)
index 0000000..e6911a4
Binary files /dev/null and b/intel/tests/gen4-3d.batch differ
diff --git a/intel/tests/gen4-3d.batch-ref.txt b/intel/tests/gen4-3d.batch-ref.txt
new file mode 100644 (file)
index 0000000..20aa1d4
--- /dev/null
@@ -0,0 +1,488 @@
+0x12300000:      0x61040000: 3DSTATE_PIPELINE_SELECT
+0x12300004:      0x79090000: 3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP
+0x12300008:      0x00000000:    dword 1
+0x1230000c:      0x61020000: STATE_SIP
+0x12300010:      0x00000000:    dword 1
+0x12300014:      0x780b0000: 3DSTATE_VF_STATISTICS
+0x12300018:      0x61010004: STATE_BASE_ADDRESS
+0x1230001c:      0x00000001:    general state base address 0x00000000
+0x12300020:      0x00000001:    surface state base address 0x00000000
+0x12300024:      0x00000001:    indirect state base address 0x00000000
+0x12300028:      0x00000001:    general state upper bound disabled
+0x1230002c:      0x00000001:    indirect state upper bound disabled
+0x12300030:      0x78010004: 3DSTATE_BINDING_TABLE_POINTERS
+0x12300034:      0x00007e20:    VS binding table
+0x12300038:      0x00000000:    GS binding table
+0x1230003c:      0x00000000:    Clip binding table
+0x12300040:      0x00000000:    SF binding table
+0x12300044:      0x00007e20:    WM binding table
+0x12300048:      0x79010003: 3DSTATE_CONSTANT_COLOR
+0x1230004c:      0x00000000:    dword 1
+0x12300050:      0x00000000:    dword 2
+0x12300054:      0x00000000:    dword 3
+0x12300058:      0x00000000:    dword 4
+0x1230005c:      0x79050003: 3DSTATE_DEPTH_BUFFER
+0x12300060:      0x2c0805ff:    2D, z24s8, pitch = 1536 bytes, tiled
+0x12300064:      0x00000000:    depth offset
+0x12300068:      0x09584ac0:    300x300
+0x1230006c:      0x00000000:    volume depth
+0x12300070:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300074:      0x00007d60:    VS state
+0x12300078:      0x00000000:    GS state
+0x1230007c:      0x00007d21:    Clip state
+0x12300080:      0x00007d80:    SF state
+0x12300084:      0x00007de0:    WM state
+0x12300088:      0x00007fc0:    CC state
+0x1230008c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300090:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300094:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x12300098:      0x60010000: CS_URB_STATE
+0x1230009c:      0x00000024:    entry_size: 2 [192 bytes], n_entries: 4
+0x123000a0:      0x79000002: 3DSTATE_DRAWING_RECTANGLE
+0x123000a4:      0x00000000:    top left: 0,0
+0x123000a8:      0x012b012b:    bottom right: 299,299
+0x123000ac:      0x00000000:    origin: 0,0
+0x123000b0:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123000b4:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x123000b8:      0x00000000:    buffer address
+0x123000bc:      0x00000000:    max index
+0x123000c0:      0x00000000:    mbz
+0x123000c4:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123000c8:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123000cc:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123000d0:      0x60020100: CONSTANT_BUFFER: valid
+0x123000d4:      0x00000001:    offset: 0x00000000, length: 128 bytes
+0x123000d8:      0x7b001804: 3DPRIMITIVE: tri fan sequential
+0x123000dc:      0x00000004:    vertex count
+0x123000e0:      0x00000000:    start vertex
+0x123000e4:      0x00000001:    instance count
+0x123000e8:      0x00000000:    start instance
+0x123000ec:      0x00000000:    index bias
+0x123000f0:      0x78010004: 3DSTATE_BINDING_TABLE_POINTERS
+0x123000f4:      0x00007b40:    VS binding table
+0x123000f8:      0x00000000:    GS binding table
+0x123000fc:      0x00000000:    Clip binding table
+0x12300100:      0x00000000:    SF binding table
+0x12300104:      0x00007b40:    WM binding table
+0x12300108:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x1230010c:      0x00007aa0:    VS state
+0x12300110:      0x00007a41:    GS state
+0x12300114:      0x00007a61:    Clip state
+0x12300118:      0x00007ac0:    SF state
+0x1230011c:      0x00007b00:    WM state
+0x12300120:      0x00007cc0:    CC state
+0x12300124:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300128:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x1230012c:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x12300130:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300134:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x12300138:      0x00000000:    buffer address
+0x1230013c:      0x00000000:    max index
+0x12300140:      0x00000000:    mbz
+0x12300144:      0x60020100: CONSTANT_BUFFER: valid
+0x12300148:      0x00000082:    offset: 0x00000080, length: 192 bytes
+0x1230014c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300150:      0x00000052:    vertex count
+0x12300154:      0x00000000:    start vertex
+0x12300158:      0x00000001:    instance count
+0x1230015c:      0x00000000:    start instance
+0x12300160:      0x00000000:    index bias
+0x12300164:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300168:      0x00007aa0:    VS state
+0x1230016c:      0x00007a21:    GS state
+0x12300170:      0x00007a61:    Clip state
+0x12300174:      0x00007ac0:    SF state
+0x12300178:      0x00007b00:    WM state
+0x1230017c:      0x00007cc0:    CC state
+0x12300180:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300184:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300188:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230018c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300190:      0x00000082:    offset: 0x00000080, length: 192 bytes
+0x12300194:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300198:      0x00000050:    vertex count
+0x1230019c:      0x00000052:    start vertex
+0x123001a0:      0x00000001:    instance count
+0x123001a4:      0x00000000:    start instance
+0x123001a8:      0x00000000:    index bias
+0x123001ac:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123001b0:      0x00007aa0:    VS state
+0x123001b4:      0x00007a01:    GS state
+0x123001b8:      0x00007a61:    Clip state
+0x123001bc:      0x00007ac0:    SF state
+0x123001c0:      0x00007b00:    WM state
+0x123001c4:      0x00007cc0:    CC state
+0x123001c8:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123001cc:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x123001d0:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x123001d4:      0x60020100: CONSTANT_BUFFER: valid
+0x123001d8:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x123001dc:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123001e0:      0x00000052:    vertex count
+0x123001e4:      0x000000a2:    start vertex
+0x123001e8:      0x00000001:    instance count
+0x123001ec:      0x00000000:    start instance
+0x123001f0:      0x00000000:    index bias
+0x123001f4:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123001f8:      0x00007aa0:    VS state
+0x123001fc:      0x000079e1:    GS state
+0x12300200:      0x00007a61:    Clip state
+0x12300204:      0x00007ac0:    SF state
+0x12300208:      0x00007b00:    WM state
+0x1230020c:      0x00007cc0:    CC state
+0x12300210:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300214:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300218:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230021c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300220:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x12300224:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300228:      0x00000050:    vertex count
+0x1230022c:      0x000000f4:    start vertex
+0x12300230:      0x00000001:    instance count
+0x12300234:      0x00000000:    start instance
+0x12300238:      0x00000000:    index bias
+0x1230023c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300240:      0x00007aa0:    VS state
+0x12300244:      0x000079c1:    GS state
+0x12300248:      0x00007a61:    Clip state
+0x1230024c:      0x00007ac0:    SF state
+0x12300250:      0x00007b00:    WM state
+0x12300254:      0x00007cc0:    CC state
+0x12300258:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230025c:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300260:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x12300264:      0x60020100: CONSTANT_BUFFER: valid
+0x12300268:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x1230026c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300270:      0x000079a0:    VS state
+0x12300274:      0x000079c1:    GS state
+0x12300278:      0x00007a61:    Clip state
+0x1230027c:      0x00007ac0:    SF state
+0x12300280:      0x00007b00:    WM state
+0x12300284:      0x00007cc0:    CC state
+0x12300288:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230028c:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300290:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x12300294:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300298:      0x00000018:    buffer 0: sequential, pitch 24b
+0x1230029c:      0x00000f48:    buffer address
+0x123002a0:      0x00000000:    max index
+0x123002a4:      0x00000000:    mbz
+0x123002a8:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x123002ac:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123002b0:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123002b4:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x123002b8:      0x11130004:    (X, Y, Z, 1.0), dst offset 0x10 bytes
+0x123002bc:      0x60020100: CONSTANT_BUFFER: valid
+0x123002c0:      0x00000202:    offset: 0x00000200, length: 192 bytes
+0x123002c4:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123002c8:      0x000000a2:    vertex count
+0x123002cc:      0x00000000:    start vertex
+0x123002d0:      0x00000001:    instance count
+0x123002d4:      0x00000000:    start instance
+0x123002d8:      0x00000000:    index bias
+0x123002dc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123002e0:      0x000079a0:    VS state
+0x123002e4:      0x00000000:    GS state
+0x123002e8:      0x00007901:    Clip state
+0x123002ec:      0x00007940:    SF state
+0x123002f0:      0x00007960:    WM state
+0x123002f4:      0x00007cc0:    CC state
+0x123002f8:      0x00000000: MI_NOOP
+0x123002fc:      0x00000000: MI_NOOP
+0x12300300:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300304:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300308:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230030c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300310:      0x00000202:    offset: 0x00000200, length: 192 bytes
+0x12300314:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x12300318:      0x0000002a:    vertex count
+0x1230031c:      0x000000a2:    start vertex
+0x12300320:      0x00000001:    instance count
+0x12300324:      0x00000000:    start instance
+0x12300328:      0x00000000:    index bias
+0x1230032c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300330:      0x00007860:    VS state
+0x12300334:      0x00007801:    GS state
+0x12300338:      0x00007821:    Clip state
+0x1230033c:      0x00007880:    SF state
+0x12300340:      0x000078a0:    WM state
+0x12300344:      0x00007cc0:    CC state
+0x12300348:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230034c:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300350:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x12300354:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300358:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x1230035c:      0x00002268:    buffer address
+0x12300360:      0x00000000:    max index
+0x12300364:      0x00000000:    mbz
+0x12300368:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x1230036c:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300370:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300374:      0x60020100: CONSTANT_BUFFER: valid
+0x12300378:      0x000002c2:    offset: 0x000002c0, length: 192 bytes
+0x1230037c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300380:      0x0000002a:    vertex count
+0x12300384:      0x00000000:    start vertex
+0x12300388:      0x00000001:    instance count
+0x1230038c:      0x00000000:    start instance
+0x12300390:      0x00000000:    index bias
+0x12300394:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300398:      0x00007860:    VS state
+0x1230039c:      0x000077e1:    GS state
+0x123003a0:      0x00007821:    Clip state
+0x123003a4:      0x00007880:    SF state
+0x123003a8:      0x000078a0:    WM state
+0x123003ac:      0x00007cc0:    CC state
+0x123003b0:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123003b4:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x123003b8:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x123003bc:      0x60020100: CONSTANT_BUFFER: valid
+0x123003c0:      0x000002c2:    offset: 0x000002c0, length: 192 bytes
+0x123003c4:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x123003c8:      0x00000028:    vertex count
+0x123003cc:      0x0000002a:    start vertex
+0x123003d0:      0x00000001:    instance count
+0x123003d4:      0x00000000:    start instance
+0x123003d8:      0x00000000:    index bias
+0x123003dc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123003e0:      0x00007860:    VS state
+0x123003e4:      0x000077c1:    GS state
+0x123003e8:      0x00007821:    Clip state
+0x123003ec:      0x00007880:    SF state
+0x123003f0:      0x000078a0:    WM state
+0x123003f4:      0x00007cc0:    CC state
+0x123003f8:      0x00000000: MI_NOOP
+0x123003fc:      0x00000000: MI_NOOP
+0x12300400:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300404:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300408:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230040c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300410:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x12300414:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300418:      0x0000002a:    vertex count
+0x1230041c:      0x00000052:    start vertex
+0x12300420:      0x00000001:    instance count
+0x12300424:      0x00000000:    start instance
+0x12300428:      0x00000000:    index bias
+0x1230042c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300430:      0x00007860:    VS state
+0x12300434:      0x000077a1:    GS state
+0x12300438:      0x00007821:    Clip state
+0x1230043c:      0x00007880:    SF state
+0x12300440:      0x000078a0:    WM state
+0x12300444:      0x00007cc0:    CC state
+0x12300448:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230044c:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300450:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x12300454:      0x60020100: CONSTANT_BUFFER: valid
+0x12300458:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x1230045c:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300460:      0x00000028:    vertex count
+0x12300464:      0x0000007c:    start vertex
+0x12300468:      0x00000001:    instance count
+0x1230046c:      0x00000000:    start instance
+0x12300470:      0x00000000:    index bias
+0x12300474:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300478:      0x00007860:    VS state
+0x1230047c:      0x00007781:    GS state
+0x12300480:      0x00007821:    Clip state
+0x12300484:      0x00007880:    SF state
+0x12300488:      0x000078a0:    WM state
+0x1230048c:      0x00007cc0:    CC state
+0x12300490:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300494:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300498:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230049c:      0x60020100: CONSTANT_BUFFER: valid
+0x123004a0:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x123004a4:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123004a8:      0x00007760:    VS state
+0x123004ac:      0x00007781:    GS state
+0x123004b0:      0x00007821:    Clip state
+0x123004b4:      0x00007880:    SF state
+0x123004b8:      0x000078a0:    WM state
+0x123004bc:      0x00007cc0:    CC state
+0x123004c0:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123004c4:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x123004c8:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x123004cc:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123004d0:      0x00000018:    buffer 0: sequential, pitch 24b
+0x123004d4:      0x00002a30:    buffer address
+0x123004d8:      0x00000000:    max index
+0x123004dc:      0x00000000:    mbz
+0x123004e0:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x123004e4:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123004e8:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123004ec:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x123004f0:      0x11130004:    (X, Y, Z, 1.0), dst offset 0x10 bytes
+0x123004f4:      0x60020100: CONSTANT_BUFFER: valid
+0x123004f8:      0x00000442:    offset: 0x00000440, length: 192 bytes
+0x123004fc:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300500:      0x00000052:    vertex count
+0x12300504:      0x00000000:    start vertex
+0x12300508:      0x00000001:    instance count
+0x1230050c:      0x00000000:    start instance
+0x12300510:      0x00000000:    index bias
+0x12300514:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300518:      0x00007760:    VS state
+0x1230051c:      0x00000000:    GS state
+0x12300520:      0x000076c1:    Clip state
+0x12300524:      0x00007700:    SF state
+0x12300528:      0x00007720:    WM state
+0x1230052c:      0x00007cc0:    CC state
+0x12300530:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300534:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300538:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230053c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300540:      0x00000442:    offset: 0x00000440, length: 192 bytes
+0x12300544:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x12300548:      0x00000016:    vertex count
+0x1230054c:      0x00000052:    start vertex
+0x12300550:      0x00000001:    instance count
+0x12300554:      0x00000000:    start instance
+0x12300558:      0x00000000:    index bias
+0x1230055c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300560:      0x00007620:    VS state
+0x12300564:      0x000075c1:    GS state
+0x12300568:      0x000075e1:    Clip state
+0x1230056c:      0x00007640:    SF state
+0x12300570:      0x00007660:    WM state
+0x12300574:      0x00007cc0:    CC state
+0x12300578:      0x00000000: MI_NOOP
+0x1230057c:      0x00000000: MI_NOOP
+0x12300580:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300584:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300588:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230058c:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300590:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x12300594:      0x000033f0:    buffer address
+0x12300598:      0x00000000:    max index
+0x1230059c:      0x00000000:    mbz
+0x123005a0:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123005a4:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123005a8:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123005ac:      0x60020100: CONSTANT_BUFFER: valid
+0x123005b0:      0x00000502:    offset: 0x00000500, length: 192 bytes
+0x123005b4:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123005b8:      0x0000002a:    vertex count
+0x123005bc:      0x00000000:    start vertex
+0x123005c0:      0x00000001:    instance count
+0x123005c4:      0x00000000:    start instance
+0x123005c8:      0x00000000:    index bias
+0x123005cc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123005d0:      0x00007620:    VS state
+0x123005d4:      0x000075a1:    GS state
+0x123005d8:      0x000075e1:    Clip state
+0x123005dc:      0x00007640:    SF state
+0x123005e0:      0x00007660:    WM state
+0x123005e4:      0x00007cc0:    CC state
+0x123005e8:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123005ec:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x123005f0:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x123005f4:      0x60020100: CONSTANT_BUFFER: valid
+0x123005f8:      0x00000502:    offset: 0x00000500, length: 192 bytes
+0x123005fc:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300600:      0x00000028:    vertex count
+0x12300604:      0x0000002a:    start vertex
+0x12300608:      0x00000001:    instance count
+0x1230060c:      0x00000000:    start instance
+0x12300610:      0x00000000:    index bias
+0x12300614:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300618:      0x00007620:    VS state
+0x1230061c:      0x00007581:    GS state
+0x12300620:      0x000075e1:    Clip state
+0x12300624:      0x00007640:    SF state
+0x12300628:      0x00007660:    WM state
+0x1230062c:      0x00007cc0:    CC state
+0x12300630:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300634:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300638:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230063c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300640:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x12300644:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300648:      0x0000002a:    vertex count
+0x1230064c:      0x00000052:    start vertex
+0x12300650:      0x00000001:    instance count
+0x12300654:      0x00000000:    start instance
+0x12300658:      0x00000000:    index bias
+0x1230065c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300660:      0x00007620:    VS state
+0x12300664:      0x00007561:    GS state
+0x12300668:      0x000075e1:    Clip state
+0x1230066c:      0x00007640:    SF state
+0x12300670:      0x00007660:    WM state
+0x12300674:      0x00007cc0:    CC state
+0x12300678:      0x00000000: MI_NOOP
+0x1230067c:      0x00000000: MI_NOOP
+0x12300680:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300684:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300688:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230068c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300690:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x12300694:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300698:      0x00000028:    vertex count
+0x1230069c:      0x0000007c:    start vertex
+0x123006a0:      0x00000001:    instance count
+0x123006a4:      0x00000000:    start instance
+0x123006a8:      0x00000000:    index bias
+0x123006ac:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123006b0:      0x00007620:    VS state
+0x123006b4:      0x00007541:    GS state
+0x123006b8:      0x000075e1:    Clip state
+0x123006bc:      0x00007640:    SF state
+0x123006c0:      0x00007660:    WM state
+0x123006c4:      0x00007cc0:    CC state
+0x123006c8:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123006cc:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x123006d0:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x123006d4:      0x60020100: CONSTANT_BUFFER: valid
+0x123006d8:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x123006dc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123006e0:      0x00007520:    VS state
+0x123006e4:      0x00007541:    GS state
+0x123006e8:      0x000075e1:    Clip state
+0x123006ec:      0x00007640:    SF state
+0x123006f0:      0x00007660:    WM state
+0x123006f4:      0x00007cc0:    CC state
+0x123006f8:      0x00000000: MI_NOOP
+0x123006fc:      0x00000000: MI_NOOP
+0x12300700:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300704:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300708:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230070c:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300710:      0x00000018:    buffer 0: sequential, pitch 24b
+0x12300714:      0x00003bb8:    buffer address
+0x12300718:      0x00000000:    max index
+0x1230071c:      0x00000000:    mbz
+0x12300720:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x12300724:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300728:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x1230072c:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x12300730:      0x11130004:    (X, Y, Z, 1.0), dst offset 0x10 bytes
+0x12300734:      0x60020100: CONSTANT_BUFFER: valid
+0x12300738:      0x00000682:    offset: 0x00000680, length: 192 bytes
+0x1230073c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300740:      0x00000052:    vertex count
+0x12300744:      0x00000000:    start vertex
+0x12300748:      0x00000001:    instance count
+0x1230074c:      0x00000000:    start instance
+0x12300750:      0x00000000:    index bias
+0x12300754:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300758:      0x00007520:    VS state
+0x1230075c:      0x00000000:    GS state
+0x12300760:      0x00007481:    Clip state
+0x12300764:      0x000074c0:    SF state
+0x12300768:      0x000074e0:    WM state
+0x1230076c:      0x00007cc0:    CC state
+0x12300770:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300774:      0x0320a020:    vs fence: 32, clip_fence: 50, gs_fence: 40
+0x12300778:      0x10000042:    sf fence: 66, vfe_fence: 0, cs_fence: 256
+0x1230077c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300780:      0x00000682:    offset: 0x00000680, length: 192 bytes
+0x12300784:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x12300788:      0x00000016:    vertex count
+0x1230078c:      0x00000052:    start vertex
+0x12300790:      0x00000001:    instance count
+0x12300794:      0x00000000:    start instance
+0x12300798:      0x00000000:    index bias
+0x1230079c:      0x05000000: MI_BATCH_BUFFER_END
diff --git a/intel/tests/gen4-3d.batch.sh b/intel/tests/gen4-3d.batch.sh
new file mode 100644 (file)
index 0000000..a94057f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST_FILENAME=`echo "$0" | sed 's|.sh||'`
+./test_decode $TEST_FILENAME
+
+ret=$?
+
+# pretty-print a diff showing what happened, and leave the dumped
+# around for possibly moving over the ref.
+if test $ret = 1; then
+    REF_FILENAME="$TEST_FILENAME-ref.txt"
+    NEW_FILENAME="$TEST_FILENAME-new.txt"
+    ./test_decode $TEST_FILENAME -dump > $NEW_FILENAME
+    if test $? = 0; then
+       echo "Differences:"
+       diff -u $REF_FILENAME $NEW_FILENAME
+    fi
+fi
+
+exit $ret
diff --git a/intel/tests/gen5-3d.batch b/intel/tests/gen5-3d.batch
new file mode 100644 (file)
index 0000000..cf9d8d8
Binary files /dev/null and b/intel/tests/gen5-3d.batch differ
diff --git a/intel/tests/gen5-3d.batch-ref.txt b/intel/tests/gen5-3d.batch-ref.txt
new file mode 100644 (file)
index 0000000..a0271ab
--- /dev/null
@@ -0,0 +1,512 @@
+0x12300000:      0x69040000: 3DSTATE_PIPELINE_SELECT
+0x12300004:      0x79090000: 3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP
+0x12300008:      0x00000000:    dword 1
+0x1230000c:      0x61020000: STATE_SIP
+0x12300010:      0x00000000:    dword 1
+0x12300014:      0x680b0000: 3DSTATE_VF_STATISTICS
+0x12300018:      0x61010006: STATE_BASE_ADDRESS
+0x1230001c:      0x00000001:    general state base address 0x00000000
+0x12300020:      0x00000001:    surface state base address 0x00000000
+0x12300024:      0x00000001:    indirect state base address 0x00000000
+0x12300028:      0x00000001:    instruction state base address 0x00000000
+0x1230002c:      0x00000001:    general state upper bound disabled
+0x12300030:      0x00000001:    indirect state upper bound disabled
+0x12300034:      0x00000001:    instruction state upper bound disabled
+0x12300038:      0x78010004: 3DSTATE_BINDING_TABLE_POINTERS
+0x1230003c:      0x00007e20:    VS binding table
+0x12300040:      0x00000000:    GS binding table
+0x12300044:      0x00000000:    Clip binding table
+0x12300048:      0x00000000:    SF binding table
+0x1230004c:      0x00007e20:    WM binding table
+0x12300050:      0x79010003: 3DSTATE_CONSTANT_COLOR
+0x12300054:      0x00000000:    dword 1
+0x12300058:      0x00000000:    dword 2
+0x1230005c:      0x00000000:    dword 3
+0x12300060:      0x00000000:    dword 4
+0x12300064:      0x79050004: 3DSTATE_DEPTH_BUFFER
+0x12300068:      0x2c0805ff:    2D, z24s8, pitch = 1536 bytes, tiled, HiZ 0, Seperate Stencil 0
+0x1230006c:      0x00000000:    depth offset
+0x12300070:      0x09584ac0:    300x300
+0x12300074:      0x00000000:    volume depth
+0x12300078:      0x00000000:    
+0x1230007c:      0x02000000: MI_FLUSH
+0x12300080:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300084:      0x00007d60:    VS state
+0x12300088:      0x00000000:    GS state
+0x1230008c:      0x00007d21:    Clip state
+0x12300090:      0x00007d80:    SF state
+0x12300094:      0x00007de0:    WM state
+0x12300098:      0x00007fc0:    CC state
+0x1230009c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123000a0:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123000a4:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123000a8:      0x60010000: CS_URB_STATE
+0x123000ac:      0x00000024:    entry_size: 2 [192 bytes], n_entries: 4
+0x123000b0:      0x79000002: 3DSTATE_DRAWING_RECTANGLE
+0x123000b4:      0x00000000:    top left: 0,0
+0x123000b8:      0x012b012b:    bottom right: 299,299
+0x123000bc:      0x00000000:    origin: 0,0
+0x123000c0:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123000c4:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x123000c8:      0x00000000:    buffer address
+0x123000cc:      0x0000ffff:    max index
+0x123000d0:      0x00000000:    mbz
+0x123000d4:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123000d8:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123000dc:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123000e0:      0x60020100: CONSTANT_BUFFER: valid
+0x123000e4:      0x00000001:    offset: 0x00000000, length: 128 bytes
+0x123000e8:      0x7b001804: 3DPRIMITIVE: tri fan sequential
+0x123000ec:      0x00000004:    vertex count
+0x123000f0:      0x00000000:    start vertex
+0x123000f4:      0x00000001:    instance count
+0x123000f8:      0x00000000:    start instance
+0x123000fc:      0x00000000:    index bias
+0x12300100:      0x78010004: 3DSTATE_BINDING_TABLE_POINTERS
+0x12300104:      0x00007b40:    VS binding table
+0x12300108:      0x00000000:    GS binding table
+0x1230010c:      0x00000000:    Clip binding table
+0x12300110:      0x00000000:    SF binding table
+0x12300114:      0x00007b40:    WM binding table
+0x12300118:      0x02000000: MI_FLUSH
+0x1230011c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300120:      0x00007aa0:    VS state
+0x12300124:      0x00007a41:    GS state
+0x12300128:      0x00007a61:    Clip state
+0x1230012c:      0x00007ac0:    SF state
+0x12300130:      0x00007b00:    WM state
+0x12300134:      0x00007cc0:    CC state
+0x12300138:      0x00000000: MI_NOOP
+0x1230013c:      0x00000000: MI_NOOP
+0x12300140:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300144:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300148:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x1230014c:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300150:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x12300154:      0x00000000:    buffer address
+0x12300158:      0x00007fff:    max index
+0x1230015c:      0x00000000:    mbz
+0x12300160:      0x60020100: CONSTANT_BUFFER: valid
+0x12300164:      0x00000082:    offset: 0x00000080, length: 192 bytes
+0x12300168:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x1230016c:      0x00000052:    vertex count
+0x12300170:      0x00000000:    start vertex
+0x12300174:      0x00000001:    instance count
+0x12300178:      0x00000000:    start instance
+0x1230017c:      0x00000000:    index bias
+0x12300180:      0x02000000: MI_FLUSH
+0x12300184:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300188:      0x00007aa0:    VS state
+0x1230018c:      0x00007a21:    GS state
+0x12300190:      0x00007a61:    Clip state
+0x12300194:      0x00007ac0:    SF state
+0x12300198:      0x00007b00:    WM state
+0x1230019c:      0x00007cc0:    CC state
+0x123001a0:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123001a4:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123001a8:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123001ac:      0x60020100: CONSTANT_BUFFER: valid
+0x123001b0:      0x00000082:    offset: 0x00000080, length: 192 bytes
+0x123001b4:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x123001b8:      0x00000050:    vertex count
+0x123001bc:      0x00000052:    start vertex
+0x123001c0:      0x00000001:    instance count
+0x123001c4:      0x00000000:    start instance
+0x123001c8:      0x00000000:    index bias
+0x123001cc:      0x02000000: MI_FLUSH
+0x123001d0:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123001d4:      0x00007aa0:    VS state
+0x123001d8:      0x00007a01:    GS state
+0x123001dc:      0x00007a61:    Clip state
+0x123001e0:      0x00007ac0:    SF state
+0x123001e4:      0x00007b00:    WM state
+0x123001e8:      0x00007cc0:    CC state
+0x123001ec:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123001f0:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123001f4:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123001f8:      0x60020100: CONSTANT_BUFFER: valid
+0x123001fc:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x12300200:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300204:      0x00000052:    vertex count
+0x12300208:      0x000000a2:    start vertex
+0x1230020c:      0x00000001:    instance count
+0x12300210:      0x00000000:    start instance
+0x12300214:      0x00000000:    index bias
+0x12300218:      0x02000000: MI_FLUSH
+0x1230021c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300220:      0x00007aa0:    VS state
+0x12300224:      0x000079e1:    GS state
+0x12300228:      0x00007a61:    Clip state
+0x1230022c:      0x00007ac0:    SF state
+0x12300230:      0x00007b00:    WM state
+0x12300234:      0x00007cc0:    CC state
+0x12300238:      0x00000000: MI_NOOP
+0x1230023c:      0x00000000: MI_NOOP
+0x12300240:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300244:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300248:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x1230024c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300250:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x12300254:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300258:      0x00000050:    vertex count
+0x1230025c:      0x000000f4:    start vertex
+0x12300260:      0x00000001:    instance count
+0x12300264:      0x00000000:    start instance
+0x12300268:      0x00000000:    index bias
+0x1230026c:      0x02000000: MI_FLUSH
+0x12300270:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300274:      0x00007aa0:    VS state
+0x12300278:      0x000079c1:    GS state
+0x1230027c:      0x00007a61:    Clip state
+0x12300280:      0x00007ac0:    SF state
+0x12300284:      0x00007b00:    WM state
+0x12300288:      0x00007cc0:    CC state
+0x1230028c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300290:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300294:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300298:      0x60020100: CONSTANT_BUFFER: valid
+0x1230029c:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x123002a0:      0x02000000: MI_FLUSH
+0x123002a4:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123002a8:      0x000079a0:    VS state
+0x123002ac:      0x000079c1:    GS state
+0x123002b0:      0x00007a61:    Clip state
+0x123002b4:      0x00007ac0:    SF state
+0x123002b8:      0x00007b00:    WM state
+0x123002bc:      0x00007cc0:    CC state
+0x123002c0:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123002c4:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123002c8:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123002cc:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123002d0:      0x00000018:    buffer 0: sequential, pitch 24b
+0x123002d4:      0x00000f48:    buffer address
+0x123002d8:      0x00007fff:    max index
+0x123002dc:      0x00000000:    mbz
+0x123002e0:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x123002e4:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123002e8:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123002ec:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x123002f0:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123002f4:      0x60020100: CONSTANT_BUFFER: valid
+0x123002f8:      0x00000202:    offset: 0x00000200, length: 192 bytes
+0x123002fc:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300300:      0x000000a2:    vertex count
+0x12300304:      0x00000000:    start vertex
+0x12300308:      0x00000001:    instance count
+0x1230030c:      0x00000000:    start instance
+0x12300310:      0x00000000:    index bias
+0x12300314:      0x02000000: MI_FLUSH
+0x12300318:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x1230031c:      0x000079a0:    VS state
+0x12300320:      0x00000000:    GS state
+0x12300324:      0x00007901:    Clip state
+0x12300328:      0x00007940:    SF state
+0x1230032c:      0x00007960:    WM state
+0x12300330:      0x00007cc0:    CC state
+0x12300334:      0x00000000: MI_NOOP
+0x12300338:      0x00000000: MI_NOOP
+0x1230033c:      0x00000000: MI_NOOP
+0x12300340:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300344:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300348:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x1230034c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300350:      0x00000202:    offset: 0x00000200, length: 192 bytes
+0x12300354:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x12300358:      0x0000002a:    vertex count
+0x1230035c:      0x000000a2:    start vertex
+0x12300360:      0x00000001:    instance count
+0x12300364:      0x00000000:    start instance
+0x12300368:      0x00000000:    index bias
+0x1230036c:      0x02000000: MI_FLUSH
+0x12300370:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300374:      0x00007860:    VS state
+0x12300378:      0x00007801:    GS state
+0x1230037c:      0x00007821:    Clip state
+0x12300380:      0x00007880:    SF state
+0x12300384:      0x000078a0:    WM state
+0x12300388:      0x00007cc0:    CC state
+0x1230038c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300390:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300394:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300398:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x1230039c:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x123003a0:      0x00002268:    buffer address
+0x123003a4:      0x00007fff:    max index
+0x123003a8:      0x00000000:    mbz
+0x123003ac:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123003b0:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123003b4:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123003b8:      0x60020100: CONSTANT_BUFFER: valid
+0x123003bc:      0x000002c2:    offset: 0x000002c0, length: 192 bytes
+0x123003c0:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123003c4:      0x0000002a:    vertex count
+0x123003c8:      0x00000000:    start vertex
+0x123003cc:      0x00000001:    instance count
+0x123003d0:      0x00000000:    start instance
+0x123003d4:      0x00000000:    index bias
+0x123003d8:      0x02000000: MI_FLUSH
+0x123003dc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123003e0:      0x00007860:    VS state
+0x123003e4:      0x000077e1:    GS state
+0x123003e8:      0x00007821:    Clip state
+0x123003ec:      0x00007880:    SF state
+0x123003f0:      0x000078a0:    WM state
+0x123003f4:      0x00007cc0:    CC state
+0x123003f8:      0x00000000: MI_NOOP
+0x123003fc:      0x00000000: MI_NOOP
+0x12300400:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300404:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300408:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x1230040c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300410:      0x000002c2:    offset: 0x000002c0, length: 192 bytes
+0x12300414:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300418:      0x00000028:    vertex count
+0x1230041c:      0x0000002a:    start vertex
+0x12300420:      0x00000001:    instance count
+0x12300424:      0x00000000:    start instance
+0x12300428:      0x00000000:    index bias
+0x1230042c:      0x02000000: MI_FLUSH
+0x12300430:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300434:      0x00007860:    VS state
+0x12300438:      0x000077c1:    GS state
+0x1230043c:      0x00007821:    Clip state
+0x12300440:      0x00007880:    SF state
+0x12300444:      0x000078a0:    WM state
+0x12300448:      0x00007cc0:    CC state
+0x1230044c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300450:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300454:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300458:      0x60020100: CONSTANT_BUFFER: valid
+0x1230045c:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x12300460:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300464:      0x0000002a:    vertex count
+0x12300468:      0x00000052:    start vertex
+0x1230046c:      0x00000001:    instance count
+0x12300470:      0x00000000:    start instance
+0x12300474:      0x00000000:    index bias
+0x12300478:      0x02000000: MI_FLUSH
+0x1230047c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300480:      0x00007860:    VS state
+0x12300484:      0x000077a1:    GS state
+0x12300488:      0x00007821:    Clip state
+0x1230048c:      0x00007880:    SF state
+0x12300490:      0x000078a0:    WM state
+0x12300494:      0x00007cc0:    CC state
+0x12300498:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230049c:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123004a0:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123004a4:      0x60020100: CONSTANT_BUFFER: valid
+0x123004a8:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x123004ac:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x123004b0:      0x00000028:    vertex count
+0x123004b4:      0x0000007c:    start vertex
+0x123004b8:      0x00000001:    instance count
+0x123004bc:      0x00000000:    start instance
+0x123004c0:      0x00000000:    index bias
+0x123004c4:      0x02000000: MI_FLUSH
+0x123004c8:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123004cc:      0x00007860:    VS state
+0x123004d0:      0x00007781:    GS state
+0x123004d4:      0x00007821:    Clip state
+0x123004d8:      0x00007880:    SF state
+0x123004dc:      0x000078a0:    WM state
+0x123004e0:      0x00007cc0:    CC state
+0x123004e4:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123004e8:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123004ec:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123004f0:      0x60020100: CONSTANT_BUFFER: valid
+0x123004f4:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x123004f8:      0x02000000: MI_FLUSH
+0x123004fc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300500:      0x00007760:    VS state
+0x12300504:      0x00007781:    GS state
+0x12300508:      0x00007821:    Clip state
+0x1230050c:      0x00007880:    SF state
+0x12300510:      0x000078a0:    WM state
+0x12300514:      0x00007cc0:    CC state
+0x12300518:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230051c:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300520:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300524:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300528:      0x00000018:    buffer 0: sequential, pitch 24b
+0x1230052c:      0x00002a30:    buffer address
+0x12300530:      0x00007fff:    max index
+0x12300534:      0x00000000:    mbz
+0x12300538:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x1230053c:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300540:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300544:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x12300548:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x1230054c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300550:      0x00000442:    offset: 0x00000440, length: 192 bytes
+0x12300554:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300558:      0x00000052:    vertex count
+0x1230055c:      0x00000000:    start vertex
+0x12300560:      0x00000001:    instance count
+0x12300564:      0x00000000:    start instance
+0x12300568:      0x00000000:    index bias
+0x1230056c:      0x02000000: MI_FLUSH
+0x12300570:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300574:      0x00007760:    VS state
+0x12300578:      0x00000000:    GS state
+0x1230057c:      0x000076c1:    Clip state
+0x12300580:      0x00007700:    SF state
+0x12300584:      0x00007720:    WM state
+0x12300588:      0x00007cc0:    CC state
+0x1230058c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300590:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300594:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300598:      0x60020100: CONSTANT_BUFFER: valid
+0x1230059c:      0x00000442:    offset: 0x00000440, length: 192 bytes
+0x123005a0:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x123005a4:      0x00000016:    vertex count
+0x123005a8:      0x00000052:    start vertex
+0x123005ac:      0x00000001:    instance count
+0x123005b0:      0x00000000:    start instance
+0x123005b4:      0x00000000:    index bias
+0x123005b8:      0x02000000: MI_FLUSH
+0x123005bc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123005c0:      0x00007620:    VS state
+0x123005c4:      0x000075c1:    GS state
+0x123005c8:      0x000075e1:    Clip state
+0x123005cc:      0x00007640:    SF state
+0x123005d0:      0x00007660:    WM state
+0x123005d4:      0x00007cc0:    CC state
+0x123005d8:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123005dc:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123005e0:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123005e4:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123005e8:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x123005ec:      0x000033f0:    buffer address
+0x123005f0:      0x00007fff:    max index
+0x123005f4:      0x00000000:    mbz
+0x123005f8:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123005fc:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300600:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300604:      0x60020100: CONSTANT_BUFFER: valid
+0x12300608:      0x00000502:    offset: 0x00000500, length: 192 bytes
+0x1230060c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300610:      0x0000002a:    vertex count
+0x12300614:      0x00000000:    start vertex
+0x12300618:      0x00000001:    instance count
+0x1230061c:      0x00000000:    start instance
+0x12300620:      0x00000000:    index bias
+0x12300624:      0x02000000: MI_FLUSH
+0x12300628:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x1230062c:      0x00007620:    VS state
+0x12300630:      0x000075a1:    GS state
+0x12300634:      0x000075e1:    Clip state
+0x12300638:      0x00007640:    SF state
+0x1230063c:      0x00007660:    WM state
+0x12300640:      0x00007cc0:    CC state
+0x12300644:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300648:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x1230064c:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300650:      0x60020100: CONSTANT_BUFFER: valid
+0x12300654:      0x00000502:    offset: 0x00000500, length: 192 bytes
+0x12300658:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x1230065c:      0x00000028:    vertex count
+0x12300660:      0x0000002a:    start vertex
+0x12300664:      0x00000001:    instance count
+0x12300668:      0x00000000:    start instance
+0x1230066c:      0x00000000:    index bias
+0x12300670:      0x02000000: MI_FLUSH
+0x12300674:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300678:      0x00007620:    VS state
+0x1230067c:      0x00007581:    GS state
+0x12300680:      0x000075e1:    Clip state
+0x12300684:      0x00007640:    SF state
+0x12300688:      0x00007660:    WM state
+0x1230068c:      0x00007cc0:    CC state
+0x12300690:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300694:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300698:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x1230069c:      0x60020100: CONSTANT_BUFFER: valid
+0x123006a0:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x123006a4:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123006a8:      0x0000002a:    vertex count
+0x123006ac:      0x00000052:    start vertex
+0x123006b0:      0x00000001:    instance count
+0x123006b4:      0x00000000:    start instance
+0x123006b8:      0x00000000:    index bias
+0x123006bc:      0x02000000: MI_FLUSH
+0x123006c0:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123006c4:      0x00007620:    VS state
+0x123006c8:      0x00007561:    GS state
+0x123006cc:      0x000075e1:    Clip state
+0x123006d0:      0x00007640:    SF state
+0x123006d4:      0x00007660:    WM state
+0x123006d8:      0x00007cc0:    CC state
+0x123006dc:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123006e0:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123006e4:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123006e8:      0x60020100: CONSTANT_BUFFER: valid
+0x123006ec:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x123006f0:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x123006f4:      0x00000028:    vertex count
+0x123006f8:      0x0000007c:    start vertex
+0x123006fc:      0x00000001:    instance count
+0x12300700:      0x00000000:    start instance
+0x12300704:      0x00000000:    index bias
+0x12300708:      0x02000000: MI_FLUSH
+0x1230070c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300710:      0x00007620:    VS state
+0x12300714:      0x00007541:    GS state
+0x12300718:      0x000075e1:    Clip state
+0x1230071c:      0x00007640:    SF state
+0x12300720:      0x00007660:    WM state
+0x12300724:      0x00007cc0:    CC state
+0x12300728:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230072c:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300730:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300734:      0x60020100: CONSTANT_BUFFER: valid
+0x12300738:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x1230073c:      0x02000000: MI_FLUSH
+0x12300740:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300744:      0x00007520:    VS state
+0x12300748:      0x00007541:    GS state
+0x1230074c:      0x000075e1:    Clip state
+0x12300750:      0x00007640:    SF state
+0x12300754:      0x00007660:    WM state
+0x12300758:      0x00007cc0:    CC state
+0x1230075c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300760:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x12300764:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x12300768:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x1230076c:      0x00000018:    buffer 0: sequential, pitch 24b
+0x12300770:      0x00003bb8:    buffer address
+0x12300774:      0x00007fff:    max index
+0x12300778:      0x00000000:    mbz
+0x1230077c:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x12300780:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300784:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300788:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x1230078c:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300790:      0x60020100: CONSTANT_BUFFER: valid
+0x12300794:      0x00000682:    offset: 0x00000680, length: 192 bytes
+0x12300798:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x1230079c:      0x00000052:    vertex count
+0x123007a0:      0x00000000:    start vertex
+0x123007a4:      0x00000001:    instance count
+0x123007a8:      0x00000000:    start instance
+0x123007ac:      0x00000000:    index bias
+0x123007b0:      0x02000000: MI_FLUSH
+0x123007b4:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123007b8:      0x00007520:    VS state
+0x123007bc:      0x00000000:    GS state
+0x123007c0:      0x00007481:    Clip state
+0x123007c4:      0x000074c0:    SF state
+0x123007c8:      0x000074e0:    WM state
+0x123007cc:      0x00007cc0:    CC state
+0x123007d0:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123007d4:      0x12444100:    vs fence: 256, clip_fence: 292, gs_fence: 272
+0x123007d8:      0x40000184:    sf fence: 388, vfe_fence: 0, cs_fence: 1024
+0x123007dc:      0x60020100: CONSTANT_BUFFER: valid
+0x123007e0:      0x00000682:    offset: 0x00000680, length: 192 bytes
+0x123007e4:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x123007e8:      0x00000016:    vertex count
+0x123007ec:      0x00000052:    start vertex
+0x123007f0:      0x00000001:    instance count
+0x123007f4:      0x00000000:    start instance
+0x123007f8:      0x00000000:    index bias
+0x123007fc:      0x05000000: MI_BATCH_BUFFER_END
diff --git a/intel/tests/gen5-3d.batch.sh b/intel/tests/gen5-3d.batch.sh
new file mode 100644 (file)
index 0000000..a94057f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST_FILENAME=`echo "$0" | sed 's|.sh||'`
+./test_decode $TEST_FILENAME
+
+ret=$?
+
+# pretty-print a diff showing what happened, and leave the dumped
+# around for possibly moving over the ref.
+if test $ret = 1; then
+    REF_FILENAME="$TEST_FILENAME-ref.txt"
+    NEW_FILENAME="$TEST_FILENAME-new.txt"
+    ./test_decode $TEST_FILENAME -dump > $NEW_FILENAME
+    if test $? = 0; then
+       echo "Differences:"
+       diff -u $REF_FILENAME $NEW_FILENAME
+    fi
+fi
+
+exit $ret
diff --git a/intel/tests/gen6-3d.batch b/intel/tests/gen6-3d.batch
new file mode 100644 (file)
index 0000000..d57147e
Binary files /dev/null and b/intel/tests/gen6-3d.batch differ
diff --git a/intel/tests/gen6-3d.batch-ref.txt b/intel/tests/gen6-3d.batch-ref.txt
new file mode 100644 (file)
index 0000000..9499ed1
--- /dev/null
@@ -0,0 +1,990 @@
+0x12300000:      0x7a000002: PIPE_CONTROL
+0x12300004:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300008:      0x00000000:    
+0x1230000c:      0x00000000:    
+0x12300010:      0x7a000002: PIPE_CONTROL
+0x12300014:      0x00004000:    qword write, 
+0x12300018:      0x00000000:    
+0x1230001c:      0x00000000:    
+0x12300020:      0x69040000: 3DSTATE_PIPELINE_SELECT
+0x12300024:      0x790d0001: 3DSTATE_MULTISAMPLE
+0x12300028:      0x00000000:    dword 1
+0x1230002c:      0x00000000:    dword 2
+0x12300030:      0x78180000: 3DSTATE_SAMPLE_MASK
+0x12300034:      0x00000001:    dword 1
+0x12300038:      0x790b0002: 3DSTATE_GS_SVB_INDEX
+0x1230003c:      0x00000000:    dword 1
+0x12300040:      0x00000000:    dword 2
+0x12300044:      0xffffffff:    dword 3
+0x12300048:      0x790b0002: 3DSTATE_GS_SVB_INDEX
+0x1230004c:      0x20000000:    dword 1
+0x12300050:      0x00000000:    dword 2
+0x12300054:      0xffffffff:    dword 3
+0x12300058:      0x790b0002: 3DSTATE_GS_SVB_INDEX
+0x1230005c:      0x40000000:    dword 1
+0x12300060:      0x00000000:    dword 2
+0x12300064:      0xffffffff:    dword 3
+0x12300068:      0x790b0002: 3DSTATE_GS_SVB_INDEX
+0x1230006c:      0x60000000:    dword 1
+0x12300070:      0x00000000:    dword 2
+0x12300074:      0xffffffff:    dword 3
+0x12300078:      0x61020000: STATE_SIP
+0x1230007c:      0x00000000:    dword 1
+0x12300080:      0x680b0000: 3DSTATE_VF_STATISTICS
+0x12300084:      0x61010008: STATE_BASE_ADDRESS
+0x12300088:      0x00000001:    general state base address 0x00000000
+0x1230008c:      0x00000001:    surface state base address 0x00000000
+0x12300090:      0x00000001:    dynamic state base address 0x00000000
+0x12300094:      0x00000001:    indirect state base address 0x00000000
+0x12300098:      0x00000001:    instruction state base address 0x00000000
+0x1230009c:      0x00000001:    general state upper bound disabled
+0x123000a0:      0x00000001:    dynamic state upper bound disabled
+0x123000a4:      0x00000001:    indirect state upper bound disabled
+0x123000a8:      0x00000001:    instruction state upper bound disabled
+0x123000ac:      0x780d1c02: 3DSTATE_VIEWPORT_STATE_POINTERS
+0x123000b0:      0x00007fe0:    clip
+0x123000b4:      0x00007fc0:    sf
+0x123000b8:      0x00007fa0:    cc
+0x123000bc:      0x78050001: 3DSTATE_URB
+0x123000c0:      0x00000100:    VS entries 256, alloc size 1 (1024bit row)
+0x123000c4:      0x00000000:    GS entries 0, alloc size 1 (1024bit row)
+0x123000c8:      0x780e0002: 3DSTATE_CC_STATE_POINTERS
+0x123000cc:      0x00007f81:    blend change 1
+0x123000d0:      0x00007f01:    depth stencil change 1
+0x123000d4:      0x00007f41:    cc change 1
+0x123000d8:      0x78021302: 3DSTATE_SAMPLER_STATE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x123000dc:      0x00000000:    VS sampler state
+0x123000e0:      0x00000000:    GS sampler state
+0x123000e4:      0x00000000:    WM sampler state
+0x123000e8:      0x78150003: 3DSTATE_CONSTANT_VS_STATE
+0x123000ec:      0x00000000:    dword 1
+0x123000f0:      0x00000000:    dword 2
+0x123000f4:      0x00000000:    dword 3
+0x123000f8:      0x00000000:    dword 4
+0x123000fc:      0x78100004: 3DSTATE_VS
+0x12300100:      0x00000000:    kernel pointer
+0x12300104:      0x00000000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300108:      0x00000000:    scratch offset
+0x1230010c:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300110:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300114:      0x7a000002: PIPE_CONTROL
+0x12300118:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x1230011c:      0x00000000:    
+0x12300120:      0x00000000:    
+0x12300124:      0x78160003: 3DSTATE_CONSTANT_GS_STATE
+0x12300128:      0x00000000:    dword 1
+0x1230012c:      0x00000000:    dword 2
+0x12300130:      0x00000000:    dword 3
+0x12300134:      0x00000000:    dword 4
+0x12300138:      0x78110005: 3DSTATE_GS
+0x1230013c:      0x00000000:    kernel pointer
+0x12300140:      0x00000000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300144:      0x00000000:    scratch offset
+0x12300148:      0x00000001:    Dispatch GRF start 1, VUE read length 0, VUE read offset 0
+0x1230014c:      0x00000500:    Max Threads 1, Rendering enable
+0x12300150:      0x00000000:    Reorder disable, Discard Adjaceny disable, GS disable
+0x12300154:      0x78120002: 3DSTATE_CLIP
+0x12300158:      0x00000400:    UserClip distance cull test mask 0x0
+0x1230015c:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x12300160:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x12300164:      0x78130012: 3DSTATE_SF
+0x12300168:      0x00200810:    Attrib Out 0, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x1230016c:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300170:      0x22000000:    AA disable, CullMode 1, Scissor disable, Multisample m ode 0
+0x12300174:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300178:      0x00000000:    Global Depth Offset Constant 0.000000
+0x1230017c:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300180:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300184:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300188:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230018c:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300190:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300194:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300198:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230019c:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123001a0:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123001a4:      0x00000000:    Point Sprite TexCoord Enable
+0x123001a8:      0x00000000:    Const Interp Enable
+0x123001ac:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x123001b0:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x123001b4:      0x78171003: 3DSTATE_CONSTANT_PS_STATE
+0x123001b8:      0x00007ee0:    dword 1
+0x123001bc:      0x00000000:    dword 2
+0x123001c0:      0x00000000:    dword 3
+0x123001c4:      0x00000000:    dword 4
+0x123001c8:      0x78140007: 3DSTATE_WM
+0x123001cc:      0x000000c0:    kernel start pointer 0
+0x123001d0:      0x00000000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x123001d4:      0x00000000:    scratch offset
+0x123001d8:      0x80020002:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 2, start[1] 0, start[2] 2
+0x123001dc:      0x4e084003:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 1
+0x123001e0:      0x00000000:    Num SF output 0, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x0, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x123001e4:      0x00000000:    kernel start pointer 1
+0x123001e8:      0x00000140:    kernel start pointer 2
+0x123001ec:      0x780f0000: 3DSTATE_SCISSOR_POINTERS
+0x123001f0:      0x00007d20:    scissor rect offset
+0x123001f4:      0x78011302: 3DSTATE_BINDING_TABLE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x123001f8:      0x00007d40:    VS binding table
+0x123001fc:      0x00007d40:    GS binding table
+0x12300200:      0x00007d40:    WM binding table
+0x12300204:      0x7a000002: PIPE_CONTROL
+0x12300208:      0x00002000:    no write, depth stall, 
+0x1230020c:      0x00000000:    
+0x12300210:      0x00000000:    
+0x12300214:      0x7a000002: PIPE_CONTROL
+0x12300218:      0x00000001:    no write, depth cache flush, 
+0x1230021c:      0x00000000:    
+0x12300220:      0x00000000:    
+0x12300224:      0x7a000002: PIPE_CONTROL
+0x12300228:      0x00002000:    no write, depth stall, 
+0x1230022c:      0x00000000:    
+0x12300230:      0x00000000:    
+0x12300234:      0x79050005: 3DSTATE_DEPTH_BUFFER
+0x12300238:      0x2c6c05ff:    2D, unknown, pitch = 1536 bytes, tiled, HiZ 1, Seperate Stencil 1
+0x1230023c:      0x00000000:    depth offset
+0x12300240:      0x09584ac0:    300x300
+0x12300244:      0x00000000:    volume depth
+0x12300248:      0x00000000:    
+0x1230024c:      0x00000000:    
+0x12300250:      0x790f0001: 3D UNKNOWN: 3d_965 opcode = 0x790f
+0x12300254:      0x000005ff: MI_NOOP
+0x12300258:      0x00000000: MI_NOOP
+0x1230025c:      0x790e0001: 3D UNKNOWN: 3d_965 opcode = 0x790e
+0x12300260:      0x0000027f: MI_NOOP
+0x12300264:      0x00000000: MI_NOOP
+0x12300268:      0x79100000: 3DSTATE_CLEAR_PARAMS
+0x1230026c:      0x00000000:    dword 1
+0x12300270:      0x79000002: 3DSTATE_DRAWING_RECTANGLE
+0x12300274:      0x00000000:    top left: 0,0
+0x12300278:      0x012b012b:    bottom right: 299,299
+0x1230027c:      0x00000000:    origin: 0,0
+0x12300280:      0x790b0002: 3DSTATE_GS_SVB_INDEX
+0x12300284:      0x00000000:    dword 1
+0x12300288:      0x00000000:    dword 2
+0x1230028c:      0x00000000:    dword 3
+0x12300290:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300294:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x12300298:      0x00000000:    buffer address
+0x1230029c:      0x0000ffff:    max index
+0x123002a0:      0x00000000:    mbz
+0x123002a4:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123002a8:      0x02400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123002ac:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123002b0:      0x7b001804: 3DPRIMITIVE: tri fan sequential
+0x123002b4:      0x00000004:    vertex count
+0x123002b8:      0x00000000:    start vertex
+0x123002bc:      0x00000001:    instance count
+0x123002c0:      0x00000000:    start instance
+0x123002c4:      0x00000000:    index bias
+0x123002c8:      0x78050001: 3DSTATE_URB
+0x123002cc:      0x00000100:    VS entries 256, alloc size 1 (1024bit row)
+0x123002d0:      0x00000000:    GS entries 0, alloc size 1 (1024bit row)
+0x123002d4:      0x780e0002: 3DSTATE_CC_STATE_POINTERS
+0x123002d8:      0x00007f81:    blend change 1
+0x123002dc:      0x00007cc1:    depth stencil change 1
+0x123002e0:      0x00007d01:    cc change 1
+0x123002e4:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x123002e8:      0x00007b85:    dword 1
+0x123002ec:      0x00000000:    dword 2
+0x123002f0:      0x00000000:    dword 3
+0x123002f4:      0x00000000:    dword 4
+0x123002f8:      0x78100004: 3DSTATE_VS
+0x123002fc:      0x00000240:    kernel pointer
+0x12300300:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300304:      0x00000000:    scratch offset
+0x12300308:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x1230030c:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300310:      0x7a000002: PIPE_CONTROL
+0x12300314:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300318:      0x00000000:    
+0x1230031c:      0x00000000:    
+0x12300320:      0x7a000002: PIPE_CONTROL
+0x12300324:      0x00004000:    qword write, 
+0x12300328:      0x00000000:    
+0x1230032c:      0x00000000:    
+0x12300330:      0x7a000002: PIPE_CONTROL
+0x12300334:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300338:      0x00000000:    
+0x1230033c:      0x00000000:    
+0x12300340:      0x78120002: 3DSTATE_CLIP
+0x12300344:      0x00000400:    UserClip distance cull test mask 0x0
+0x12300348:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x1230034c:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x12300350:      0x78130012: 3DSTATE_SF
+0x12300354:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300358:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x1230035c:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x12300360:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300364:      0x00000000:    Global Depth Offset Constant 0.000000
+0x12300368:      0x00000000:    Global Depth Offset Scale 0.000000
+0x1230036c:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300370:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300374:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300378:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230037c:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300380:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300384:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300388:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230038c:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300390:      0x00000000:    Point Sprite TexCoord Enable
+0x12300394:      0x00000001:    Const Interp Enable
+0x12300398:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x1230039c:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x123003a0:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x123003a4:      0x00000000:    dword 1
+0x123003a8:      0x00000000:    dword 2
+0x123003ac:      0x00000000:    dword 3
+0x123003b0:      0x00000000:    dword 4
+0x123003b4:      0x78140007: 3DSTATE_WM
+0x123003b8:      0x00000500:    kernel start pointer 0
+0x123003bc:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x123003c0:      0x00000000:    scratch offset
+0x123003c4:      0x80020000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 2, start[1] 0, start[2] 0
+0x123003c8:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x123003cc:      0x00100000:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x0, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x123003d0:      0x00000000:    kernel start pointer 1
+0x123003d4:      0x00000500:    kernel start pointer 2
+0x123003d8:      0x78011302: 3DSTATE_BINDING_TABLE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x123003dc:      0x00007a00:    VS binding table
+0x123003e0:      0x00007a00:    GS binding table
+0x123003e4:      0x00007a00:    WM binding table
+0x123003e8:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123003ec:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x123003f0:      0x00000000:    buffer address
+0x123003f4:      0x00007fff:    max index
+0x123003f8:      0x00000000:    mbz
+0x123003fc:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300400:      0x00000052:    vertex count
+0x12300404:      0x00000000:    start vertex
+0x12300408:      0x00000001:    instance count
+0x1230040c:      0x00000000:    start instance
+0x12300410:      0x00000000:    index bias
+0x12300414:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300418:      0x00000050:    vertex count
+0x1230041c:      0x00000052:    start vertex
+0x12300420:      0x00000001:    instance count
+0x12300424:      0x00000000:    start instance
+0x12300428:      0x00000000:    index bias
+0x1230042c:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300430:      0x000078c5:    dword 1
+0x12300434:      0x00000000:    dword 2
+0x12300438:      0x00000000:    dword 3
+0x1230043c:      0x00000000:    dword 4
+0x12300440:      0x78100004: 3DSTATE_VS
+0x12300444:      0x00000240:    kernel pointer
+0x12300448:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x1230044c:      0x00000000:    scratch offset
+0x12300450:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300454:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300458:      0x7a000002: PIPE_CONTROL
+0x1230045c:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300460:      0x00000000:    
+0x12300464:      0x00000000:    
+0x12300468:      0x7a000002: PIPE_CONTROL
+0x1230046c:      0x00004000:    qword write, 
+0x12300470:      0x00000000:    
+0x12300474:      0x00000000:    
+0x12300478:      0x7a000002: PIPE_CONTROL
+0x1230047c:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300480:      0x00000000:    
+0x12300484:      0x00000000:    
+0x12300488:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x1230048c:      0x00000000:    dword 1
+0x12300490:      0x00000000:    dword 2
+0x12300494:      0x00000000:    dword 3
+0x12300498:      0x00000000:    dword 4
+0x1230049c:      0x78140007: 3DSTATE_WM
+0x123004a0:      0x00000500:    kernel start pointer 0
+0x123004a4:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x123004a8:      0x00000000:    scratch offset
+0x123004ac:      0x80020000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 2, start[1] 0, start[2] 0
+0x123004b0:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x123004b4:      0x00100000:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x0, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x123004b8:      0x00000000:    kernel start pointer 1
+0x123004bc:      0x00000500:    kernel start pointer 2
+0x123004c0:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123004c4:      0x00000052:    vertex count
+0x123004c8:      0x000000a2:    start vertex
+0x123004cc:      0x00000001:    instance count
+0x123004d0:      0x00000000:    start instance
+0x123004d4:      0x00000000:    index bias
+0x123004d8:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x123004dc:      0x00000050:    vertex count
+0x123004e0:      0x000000f4:    start vertex
+0x123004e4:      0x00000001:    instance count
+0x123004e8:      0x00000000:    start instance
+0x123004ec:      0x00000000:    index bias
+0x123004f0:      0x78050001: 3DSTATE_URB
+0x123004f4:      0x00000100:    VS entries 256, alloc size 1 (1024bit row)
+0x123004f8:      0x00000000:    GS entries 0, alloc size 1 (1024bit row)
+0x123004fc:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300500:      0x00007785:    dword 1
+0x12300504:      0x00000000:    dword 2
+0x12300508:      0x00000000:    dword 3
+0x1230050c:      0x00000000:    dword 4
+0x12300510:      0x78100004: 3DSTATE_VS
+0x12300514:      0x00000640:    kernel pointer
+0x12300518:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x1230051c:      0x00000000:    scratch offset
+0x12300520:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300524:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300528:      0x7a000002: PIPE_CONTROL
+0x1230052c:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300530:      0x00000000:    
+0x12300534:      0x00000000:    
+0x12300538:      0x7a000002: PIPE_CONTROL
+0x1230053c:      0x00004000:    qword write, 
+0x12300540:      0x00000000:    
+0x12300544:      0x00000000:    
+0x12300548:      0x7a000002: PIPE_CONTROL
+0x1230054c:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300550:      0x00000000:    
+0x12300554:      0x00000000:    
+0x12300558:      0x78130012: 3DSTATE_SF
+0x1230055c:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300560:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300564:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x12300568:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x1230056c:      0x00000000:    Global Depth Offset Constant 0.000000
+0x12300570:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300574:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300578:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230057c:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300580:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300584:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300588:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230058c:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300590:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300594:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300598:      0x00000000:    Point Sprite TexCoord Enable
+0x1230059c:      0x00000001:    Const Interp Enable
+0x123005a0:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x123005a4:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x123005a8:      0x78011302: 3DSTATE_BINDING_TABLE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x123005ac:      0x00007600:    VS binding table
+0x123005b0:      0x00007600:    GS binding table
+0x123005b4:      0x00007600:    WM binding table
+0x123005b8:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123005bc:      0x00000018:    buffer 0: sequential, pitch 24b
+0x123005c0:      0x00000f48:    buffer address
+0x123005c4:      0x00007fff:    max index
+0x123005c8:      0x00000000:    mbz
+0x123005cc:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x123005d0:      0x02400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123005d4:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123005d8:      0x0240000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x123005dc:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123005e0:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123005e4:      0x000000a2:    vertex count
+0x123005e8:      0x00000000:    start vertex
+0x123005ec:      0x00000001:    instance count
+0x123005f0:      0x00000000:    start instance
+0x123005f4:      0x00000000:    index bias
+0x123005f8:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x123005fc:      0x000074c5:    dword 1
+0x12300600:      0x00000000:    dword 2
+0x12300604:      0x00000000:    dword 3
+0x12300608:      0x00000000:    dword 4
+0x1230060c:      0x78100004: 3DSTATE_VS
+0x12300610:      0x00000640:    kernel pointer
+0x12300614:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300618:      0x00000000:    scratch offset
+0x1230061c:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300620:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300624:      0x7a000002: PIPE_CONTROL
+0x12300628:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x1230062c:      0x00000000:    
+0x12300630:      0x00000000:    
+0x12300634:      0x7a000002: PIPE_CONTROL
+0x12300638:      0x00004000:    qword write, 
+0x1230063c:      0x00000000:    
+0x12300640:      0x00000000:    
+0x12300644:      0x7a000002: PIPE_CONTROL
+0x12300648:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x1230064c:      0x00000000:    
+0x12300650:      0x00000000:    
+0x12300654:      0x78120002: 3DSTATE_CLIP
+0x12300658:      0x00000400:    UserClip distance cull test mask 0x0
+0x1230065c:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x12300660:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x12300664:      0x78130012: 3DSTATE_SF
+0x12300668:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x1230066c:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300670:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x12300674:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300678:      0x00000000:    Global Depth Offset Constant 0.000000
+0x1230067c:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300680:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300684:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300688:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230068c:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300690:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300694:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300698:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x1230069c:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123006a0:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123006a4:      0x00000000:    Point Sprite TexCoord Enable
+0x123006a8:      0x00000000:    Const Interp Enable
+0x123006ac:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x123006b0:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x123006b4:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x123006b8:      0x00000000:    dword 1
+0x123006bc:      0x00000000:    dword 2
+0x123006c0:      0x00000000:    dword 3
+0x123006c4:      0x00000000:    dword 4
+0x123006c8:      0x78140007: 3DSTATE_WM
+0x123006cc:      0x00000900:    kernel start pointer 0
+0x123006d0:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x123006d4:      0x00000000:    scratch offset
+0x123006d8:      0x80060000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 6, start[1] 0, start[2] 0
+0x123006dc:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x123006e0:      0x00100400:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x1, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x123006e4:      0x00000000:    kernel start pointer 1
+0x123006e8:      0x00000900:    kernel start pointer 2
+0x123006ec:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123006f0:      0x0000002a:    vertex count
+0x123006f4:      0x000000a2:    start vertex
+0x123006f8:      0x00000001:    instance count
+0x123006fc:      0x00000000:    start instance
+0x12300700:      0x00000000:    index bias
+0x12300704:      0x78050001: 3DSTATE_URB
+0x12300708:      0x00000100:    VS entries 256, alloc size 1 (1024bit row)
+0x1230070c:      0x00000000:    GS entries 0, alloc size 1 (1024bit row)
+0x12300710:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300714:      0x00007385:    dword 1
+0x12300718:      0x00000000:    dword 2
+0x1230071c:      0x00000000:    dword 3
+0x12300720:      0x00000000:    dword 4
+0x12300724:      0x78100004: 3DSTATE_VS
+0x12300728:      0x00000240:    kernel pointer
+0x1230072c:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300730:      0x00000000:    scratch offset
+0x12300734:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300738:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x1230073c:      0x7a000002: PIPE_CONTROL
+0x12300740:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300744:      0x00000000:    
+0x12300748:      0x00000000:    
+0x1230074c:      0x7a000002: PIPE_CONTROL
+0x12300750:      0x00004000:    qword write, 
+0x12300754:      0x00000000:    
+0x12300758:      0x00000000:    
+0x1230075c:      0x7a000002: PIPE_CONTROL
+0x12300760:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300764:      0x00000000:    
+0x12300768:      0x00000000:    
+0x1230076c:      0x78120002: 3DSTATE_CLIP
+0x12300770:      0x00000400:    UserClip distance cull test mask 0x0
+0x12300774:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x12300778:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x1230077c:      0x78130012: 3DSTATE_SF
+0x12300780:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300784:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300788:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x1230078c:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300790:      0x00000000:    Global Depth Offset Constant 0.000000
+0x12300794:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300798:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x1230079c:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007a0:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007a4:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007a8:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007ac:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007b0:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007b4:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007b8:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123007bc:      0x00000000:    Point Sprite TexCoord Enable
+0x123007c0:      0x00000001:    Const Interp Enable
+0x123007c4:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x123007c8:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x123007cc:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x123007d0:      0x00000000:    dword 1
+0x123007d4:      0x00000000:    dword 2
+0x123007d8:      0x00000000:    dword 3
+0x123007dc:      0x00000000:    dword 4
+0x123007e0:      0x78140007: 3DSTATE_WM
+0x123007e4:      0x00000500:    kernel start pointer 0
+0x123007e8:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x123007ec:      0x00000000:    scratch offset
+0x123007f0:      0x80020000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 2, start[1] 0, start[2] 0
+0x123007f4:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x123007f8:      0x00100000:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x0, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x123007fc:      0x00000000:    kernel start pointer 1
+0x12300800:      0x00000500:    kernel start pointer 2
+0x12300804:      0x78011302: 3DSTATE_BINDING_TABLE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x12300808:      0x00007200:    VS binding table
+0x1230080c:      0x00007200:    GS binding table
+0x12300810:      0x00007200:    WM binding table
+0x12300814:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300818:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x1230081c:      0x00002268:    buffer address
+0x12300820:      0x00007fff:    max index
+0x12300824:      0x00000000:    mbz
+0x12300828:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x1230082c:      0x02400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300830:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300834:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300838:      0x0000002a:    vertex count
+0x1230083c:      0x00000000:    start vertex
+0x12300840:      0x00000001:    instance count
+0x12300844:      0x00000000:    start instance
+0x12300848:      0x00000000:    index bias
+0x1230084c:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300850:      0x00000028:    vertex count
+0x12300854:      0x0000002a:    start vertex
+0x12300858:      0x00000001:    instance count
+0x1230085c:      0x00000000:    start instance
+0x12300860:      0x00000000:    index bias
+0x12300864:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300868:      0x000070c5:    dword 1
+0x1230086c:      0x00000000:    dword 2
+0x12300870:      0x00000000:    dword 3
+0x12300874:      0x00000000:    dword 4
+0x12300878:      0x78100004: 3DSTATE_VS
+0x1230087c:      0x00000240:    kernel pointer
+0x12300880:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300884:      0x00000000:    scratch offset
+0x12300888:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x1230088c:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300890:      0x7a000002: PIPE_CONTROL
+0x12300894:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300898:      0x00000000:    
+0x1230089c:      0x00000000:    
+0x123008a0:      0x7a000002: PIPE_CONTROL
+0x123008a4:      0x00004000:    qword write, 
+0x123008a8:      0x00000000:    
+0x123008ac:      0x00000000:    
+0x123008b0:      0x7a000002: PIPE_CONTROL
+0x123008b4:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x123008b8:      0x00000000:    
+0x123008bc:      0x00000000:    
+0x123008c0:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x123008c4:      0x00000000:    dword 1
+0x123008c8:      0x00000000:    dword 2
+0x123008cc:      0x00000000:    dword 3
+0x123008d0:      0x00000000:    dword 4
+0x123008d4:      0x78140007: 3DSTATE_WM
+0x123008d8:      0x00000500:    kernel start pointer 0
+0x123008dc:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x123008e0:      0x00000000:    scratch offset
+0x123008e4:      0x80020000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 2, start[1] 0, start[2] 0
+0x123008e8:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x123008ec:      0x00100000:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x0, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x123008f0:      0x00000000:    kernel start pointer 1
+0x123008f4:      0x00000500:    kernel start pointer 2
+0x123008f8:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123008fc:      0x0000002a:    vertex count
+0x12300900:      0x00000052:    start vertex
+0x12300904:      0x00000001:    instance count
+0x12300908:      0x00000000:    start instance
+0x1230090c:      0x00000000:    index bias
+0x12300910:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300914:      0x00000028:    vertex count
+0x12300918:      0x0000007c:    start vertex
+0x1230091c:      0x00000001:    instance count
+0x12300920:      0x00000000:    start instance
+0x12300924:      0x00000000:    index bias
+0x12300928:      0x78050001: 3DSTATE_URB
+0x1230092c:      0x00000100:    VS entries 256, alloc size 1 (1024bit row)
+0x12300930:      0x00000000:    GS entries 0, alloc size 1 (1024bit row)
+0x12300934:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300938:      0x00006f85:    dword 1
+0x1230093c:      0x00000000:    dword 2
+0x12300940:      0x00000000:    dword 3
+0x12300944:      0x00000000:    dword 4
+0x12300948:      0x78100004: 3DSTATE_VS
+0x1230094c:      0x00000640:    kernel pointer
+0x12300950:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300954:      0x00000000:    scratch offset
+0x12300958:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x1230095c:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300960:      0x7a000002: PIPE_CONTROL
+0x12300964:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300968:      0x00000000:    
+0x1230096c:      0x00000000:    
+0x12300970:      0x7a000002: PIPE_CONTROL
+0x12300974:      0x00004000:    qword write, 
+0x12300978:      0x00000000:    
+0x1230097c:      0x00000000:    
+0x12300980:      0x7a000002: PIPE_CONTROL
+0x12300984:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300988:      0x00000000:    
+0x1230098c:      0x00000000:    
+0x12300990:      0x78130012: 3DSTATE_SF
+0x12300994:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300998:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x1230099c:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x123009a0:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x123009a4:      0x00000000:    Global Depth Offset Constant 0.000000
+0x123009a8:      0x00000000:    Global Depth Offset Scale 0.000000
+0x123009ac:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x123009b0:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009b4:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009b8:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009bc:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009c0:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009c4:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009c8:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009cc:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x123009d0:      0x00000000:    Point Sprite TexCoord Enable
+0x123009d4:      0x00000001:    Const Interp Enable
+0x123009d8:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x123009dc:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x123009e0:      0x78011302: 3DSTATE_BINDING_TABLE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x123009e4:      0x00006e00:    VS binding table
+0x123009e8:      0x00006e00:    GS binding table
+0x123009ec:      0x00006e00:    WM binding table
+0x123009f0:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123009f4:      0x00000018:    buffer 0: sequential, pitch 24b
+0x123009f8:      0x00002a30:    buffer address
+0x123009fc:      0x00007fff:    max index
+0x12300a00:      0x00000000:    mbz
+0x12300a04:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x12300a08:      0x02400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300a0c:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300a10:      0x0240000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x12300a14:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300a18:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300a1c:      0x00000052:    vertex count
+0x12300a20:      0x00000000:    start vertex
+0x12300a24:      0x00000001:    instance count
+0x12300a28:      0x00000000:    start instance
+0x12300a2c:      0x00000000:    index bias
+0x12300a30:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300a34:      0x00006cc5:    dword 1
+0x12300a38:      0x00000000:    dword 2
+0x12300a3c:      0x00000000:    dword 3
+0x12300a40:      0x00000000:    dword 4
+0x12300a44:      0x78100004: 3DSTATE_VS
+0x12300a48:      0x00000640:    kernel pointer
+0x12300a4c:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300a50:      0x00000000:    scratch offset
+0x12300a54:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300a58:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300a5c:      0x7a000002: PIPE_CONTROL
+0x12300a60:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300a64:      0x00000000:    
+0x12300a68:      0x00000000:    
+0x12300a6c:      0x7a000002: PIPE_CONTROL
+0x12300a70:      0x00004000:    qword write, 
+0x12300a74:      0x00000000:    
+0x12300a78:      0x00000000:    
+0x12300a7c:      0x7a000002: PIPE_CONTROL
+0x12300a80:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300a84:      0x00000000:    
+0x12300a88:      0x00000000:    
+0x12300a8c:      0x78120002: 3DSTATE_CLIP
+0x12300a90:      0x00000400:    UserClip distance cull test mask 0x0
+0x12300a94:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x12300a98:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x12300a9c:      0x78130012: 3DSTATE_SF
+0x12300aa0:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300aa4:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300aa8:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x12300aac:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300ab0:      0x00000000:    Global Depth Offset Constant 0.000000
+0x12300ab4:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300ab8:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300abc:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300ac0:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300ac4:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300ac8:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300acc:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300ad0:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300ad4:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300ad8:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300adc:      0x00000000:    Point Sprite TexCoord Enable
+0x12300ae0:      0x00000000:    Const Interp Enable
+0x12300ae4:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x12300ae8:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x12300aec:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x12300af0:      0x00000000:    dword 1
+0x12300af4:      0x00000000:    dword 2
+0x12300af8:      0x00000000:    dword 3
+0x12300afc:      0x00000000:    dword 4
+0x12300b00:      0x78140007: 3DSTATE_WM
+0x12300b04:      0x00000900:    kernel start pointer 0
+0x12300b08:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300b0c:      0x00000000:    scratch offset
+0x12300b10:      0x80060000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 6, start[1] 0, start[2] 0
+0x12300b14:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x12300b18:      0x00100400:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x1, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x12300b1c:      0x00000000:    kernel start pointer 1
+0x12300b20:      0x00000900:    kernel start pointer 2
+0x12300b24:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300b28:      0x00000016:    vertex count
+0x12300b2c:      0x00000052:    start vertex
+0x12300b30:      0x00000001:    instance count
+0x12300b34:      0x00000000:    start instance
+0x12300b38:      0x00000000:    index bias
+0x12300b3c:      0x78050001: 3DSTATE_URB
+0x12300b40:      0x00000100:    VS entries 256, alloc size 1 (1024bit row)
+0x12300b44:      0x00000000:    GS entries 0, alloc size 1 (1024bit row)
+0x12300b48:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300b4c:      0x00006b85:    dword 1
+0x12300b50:      0x00000000:    dword 2
+0x12300b54:      0x00000000:    dword 3
+0x12300b58:      0x00000000:    dword 4
+0x12300b5c:      0x78100004: 3DSTATE_VS
+0x12300b60:      0x00000240:    kernel pointer
+0x12300b64:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300b68:      0x00000000:    scratch offset
+0x12300b6c:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300b70:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300b74:      0x7a000002: PIPE_CONTROL
+0x12300b78:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300b7c:      0x00000000:    
+0x12300b80:      0x00000000:    
+0x12300b84:      0x7a000002: PIPE_CONTROL
+0x12300b88:      0x00004000:    qword write, 
+0x12300b8c:      0x00000000:    
+0x12300b90:      0x00000000:    
+0x12300b94:      0x7a000002: PIPE_CONTROL
+0x12300b98:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300b9c:      0x00000000:    
+0x12300ba0:      0x00000000:    
+0x12300ba4:      0x78120002: 3DSTATE_CLIP
+0x12300ba8:      0x00000400:    UserClip distance cull test mask 0x0
+0x12300bac:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x12300bb0:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x12300bb4:      0x78130012: 3DSTATE_SF
+0x12300bb8:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300bbc:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300bc0:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x12300bc4:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300bc8:      0x00000000:    Global Depth Offset Constant 0.000000
+0x12300bcc:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300bd0:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300bd4:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300bd8:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300bdc:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300be0:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300be4:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300be8:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300bec:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300bf0:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300bf4:      0x00000000:    Point Sprite TexCoord Enable
+0x12300bf8:      0x00000001:    Const Interp Enable
+0x12300bfc:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x12300c00:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x12300c04:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x12300c08:      0x00000000:    dword 1
+0x12300c0c:      0x00000000:    dword 2
+0x12300c10:      0x00000000:    dword 3
+0x12300c14:      0x00000000:    dword 4
+0x12300c18:      0x78140007: 3DSTATE_WM
+0x12300c1c:      0x00000500:    kernel start pointer 0
+0x12300c20:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300c24:      0x00000000:    scratch offset
+0x12300c28:      0x80020000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 2, start[1] 0, start[2] 0
+0x12300c2c:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x12300c30:      0x00100000:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x0, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x12300c34:      0x00000000:    kernel start pointer 1
+0x12300c38:      0x00000500:    kernel start pointer 2
+0x12300c3c:      0x78011302: 3DSTATE_BINDING_TABLE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x12300c40:      0x00006a00:    VS binding table
+0x12300c44:      0x00006a00:    GS binding table
+0x12300c48:      0x00006a00:    WM binding table
+0x12300c4c:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300c50:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x12300c54:      0x000033f0:    buffer address
+0x12300c58:      0x00007fff:    max index
+0x12300c5c:      0x00000000:    mbz
+0x12300c60:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x12300c64:      0x02400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300c68:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300c6c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300c70:      0x0000002a:    vertex count
+0x12300c74:      0x00000000:    start vertex
+0x12300c78:      0x00000001:    instance count
+0x12300c7c:      0x00000000:    start instance
+0x12300c80:      0x00000000:    index bias
+0x12300c84:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300c88:      0x00000028:    vertex count
+0x12300c8c:      0x0000002a:    start vertex
+0x12300c90:      0x00000001:    instance count
+0x12300c94:      0x00000000:    start instance
+0x12300c98:      0x00000000:    index bias
+0x12300c9c:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300ca0:      0x000068c5:    dword 1
+0x12300ca4:      0x00000000:    dword 2
+0x12300ca8:      0x00000000:    dword 3
+0x12300cac:      0x00000000:    dword 4
+0x12300cb0:      0x78100004: 3DSTATE_VS
+0x12300cb4:      0x00000240:    kernel pointer
+0x12300cb8:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300cbc:      0x00000000:    scratch offset
+0x12300cc0:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300cc4:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300cc8:      0x7a000002: PIPE_CONTROL
+0x12300ccc:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300cd0:      0x00000000:    
+0x12300cd4:      0x00000000:    
+0x12300cd8:      0x7a000002: PIPE_CONTROL
+0x12300cdc:      0x00004000:    qword write, 
+0x12300ce0:      0x00000000:    
+0x12300ce4:      0x00000000:    
+0x12300ce8:      0x7a000002: PIPE_CONTROL
+0x12300cec:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300cf0:      0x00000000:    
+0x12300cf4:      0x00000000:    
+0x12300cf8:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x12300cfc:      0x00000000:    dword 1
+0x12300d00:      0x00000000:    dword 2
+0x12300d04:      0x00000000:    dword 3
+0x12300d08:      0x00000000:    dword 4
+0x12300d0c:      0x78140007: 3DSTATE_WM
+0x12300d10:      0x00000500:    kernel start pointer 0
+0x12300d14:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300d18:      0x00000000:    scratch offset
+0x12300d1c:      0x80020000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 2, start[1] 0, start[2] 0
+0x12300d20:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x12300d24:      0x00100000:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x0, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x12300d28:      0x00000000:    kernel start pointer 1
+0x12300d2c:      0x00000500:    kernel start pointer 2
+0x12300d30:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300d34:      0x0000002a:    vertex count
+0x12300d38:      0x00000052:    start vertex
+0x12300d3c:      0x00000001:    instance count
+0x12300d40:      0x00000000:    start instance
+0x12300d44:      0x00000000:    index bias
+0x12300d48:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300d4c:      0x00000028:    vertex count
+0x12300d50:      0x0000007c:    start vertex
+0x12300d54:      0x00000001:    instance count
+0x12300d58:      0x00000000:    start instance
+0x12300d5c:      0x00000000:    index bias
+0x12300d60:      0x78050001: 3DSTATE_URB
+0x12300d64:      0x00000100:    VS entries 256, alloc size 1 (1024bit row)
+0x12300d68:      0x00000000:    GS entries 0, alloc size 1 (1024bit row)
+0x12300d6c:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300d70:      0x00006785:    dword 1
+0x12300d74:      0x00000000:    dword 2
+0x12300d78:      0x00000000:    dword 3
+0x12300d7c:      0x00000000:    dword 4
+0x12300d80:      0x78100004: 3DSTATE_VS
+0x12300d84:      0x00000640:    kernel pointer
+0x12300d88:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300d8c:      0x00000000:    scratch offset
+0x12300d90:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300d94:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300d98:      0x7a000002: PIPE_CONTROL
+0x12300d9c:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300da0:      0x00000000:    
+0x12300da4:      0x00000000:    
+0x12300da8:      0x7a000002: PIPE_CONTROL
+0x12300dac:      0x00004000:    qword write, 
+0x12300db0:      0x00000000:    
+0x12300db4:      0x00000000:    
+0x12300db8:      0x7a000002: PIPE_CONTROL
+0x12300dbc:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300dc0:      0x00000000:    
+0x12300dc4:      0x00000000:    
+0x12300dc8:      0x78130012: 3DSTATE_SF
+0x12300dcc:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300dd0:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300dd4:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x12300dd8:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300ddc:      0x00000000:    Global Depth Offset Constant 0.000000
+0x12300de0:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300de4:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300de8:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300dec:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300df0:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300df4:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300df8:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300dfc:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300e00:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300e04:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300e08:      0x00000000:    Point Sprite TexCoord Enable
+0x12300e0c:      0x00000001:    Const Interp Enable
+0x12300e10:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x12300e14:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x12300e18:      0x78011302: 3DSTATE_BINDING_TABLE_POINTERS: VS mod 1, GS mod 1, PS mod 1
+0x12300e1c:      0x00006600:    VS binding table
+0x12300e20:      0x00006600:    GS binding table
+0x12300e24:      0x00006600:    WM binding table
+0x12300e28:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300e2c:      0x00000018:    buffer 0: sequential, pitch 24b
+0x12300e30:      0x00003bb8:    buffer address
+0x12300e34:      0x00007fff:    max index
+0x12300e38:      0x00000000:    mbz
+0x12300e3c:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x12300e40:      0x02400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300e44:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300e48:      0x0240000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x12300e4c:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300e50:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300e54:      0x00000052:    vertex count
+0x12300e58:      0x00000000:    start vertex
+0x12300e5c:      0x00000001:    instance count
+0x12300e60:      0x00000000:    start instance
+0x12300e64:      0x00000000:    index bias
+0x12300e68:      0x78151003: 3DSTATE_CONSTANT_VS_STATE
+0x12300e6c:      0x000064c5:    dword 1
+0x12300e70:      0x00000000:    dword 2
+0x12300e74:      0x00000000:    dword 3
+0x12300e78:      0x00000000:    dword 4
+0x12300e7c:      0x78100004: 3DSTATE_VS
+0x12300e80:      0x00000640:    kernel pointer
+0x12300e84:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300e88:      0x00000000:    scratch offset
+0x12300e8c:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x12300e90:      0x76000401:    Max Threads 60, Vertex Cache enable, VS func enable
+0x12300e94:      0x7a000002: PIPE_CONTROL
+0x12300e98:      0x00100002:    no write, cs stall, stall at scoreboard, 
+0x12300e9c:      0x00000000:    
+0x12300ea0:      0x00000000:    
+0x12300ea4:      0x7a000002: PIPE_CONTROL
+0x12300ea8:      0x00004000:    qword write, 
+0x12300eac:      0x00000000:    
+0x12300eb0:      0x00000000:    
+0x12300eb4:      0x7a000002: PIPE_CONTROL
+0x12300eb8:      0x00002804:    no write, depth stall, instruction cache invalidate, state cache invalidate, 
+0x12300ebc:      0x00000000:    
+0x12300ec0:      0x00000000:    
+0x12300ec4:      0x78120002: 3DSTATE_CLIP
+0x12300ec8:      0x00000400:    UserClip distance cull test mask 0x0
+0x12300ecc:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x12300ed0:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x12300ed4:      0x78130012: 3DSTATE_SF
+0x12300ed8:      0x00600810:    Attrib Out 1, Attrib Swizzle enable, VUE read length 1, VUE read offset 1
+0x12300edc:      0x00000403:    Legacy Global DepthBias disable, FrontFace fill 0, BF fill 0, VP transform enable, FrontWinding_CCW
+0x12300ee0:      0x62000000:    AA disable, CullMode 3, Scissor disable, Multisample m ode 0
+0x12300ee4:      0x4c000808:    Last Pixel disable, SubPixel Precision 8, Use PixelWidth 1
+0x12300ee8:      0x00000000:    Global Depth Offset Constant 0.000000
+0x12300eec:      0x00000000:    Global Depth Offset Scale 0.000000
+0x12300ef0:      0x00000000:    Global Depth Offset Clamp 0.000000
+0x12300ef4:      0x00000000:    Attrib 1 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 0 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300ef8:      0x00000000:    Attrib 3 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 2 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300efc:      0x00000000:    Attrib 5 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 4 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300f00:      0x00000000:    Attrib 7 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 6 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300f04:      0x00000000:    Attrib 9 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 8 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300f08:      0x00000000:    Attrib 11 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 10 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300f0c:      0x00000000:    Attrib 13 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 12 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300f10:      0x00000000:    Attrib 15 (Override , Const Source 0, Swizzle Select 0, Source 0); Attrib 14 (Override , Const Source 0, Swizzle Select 0, Source 0)
+0x12300f14:      0x00000000:    Point Sprite TexCoord Enable
+0x12300f18:      0x00000000:    Const Interp Enable
+0x12300f1c:      0x00000000:    Attrib 7-0 WrapShortest Enable
+0x12300f20:      0x00000000:    Attrib 15-8 WrapShortest Enable
+0x12300f24:      0x78170003: 3DSTATE_CONSTANT_PS_STATE
+0x12300f28:      0x00000000:    dword 1
+0x12300f2c:      0x00000000:    dword 2
+0x12300f30:      0x00000000:    dword 3
+0x12300f34:      0x00000000:    dword 4
+0x12300f38:      0x78140007: 3DSTATE_WM
+0x12300f3c:      0x00000900:    kernel start pointer 0
+0x12300f40:      0x00010000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x12300f44:      0x00000000:    scratch offset
+0x12300f48:      0x80060000:    Depth Clear 0, Depth Resolve 0, HiZ Resolve 0, Dispatch GRF start[0] 6, start[1] 0, start[2] 0
+0x12300f4c:      0x4e084002:    MaxThreads 40, PS KillPixel 0, PS computed Z 0, PS use sourceZ 0, Thread Dispatch 1, PS use sourceW 0, Dispatch32 0, Dispatch16 1, Dispatch8 0
+0x12300f50:      0x00100400:    Num SF output 1, Pos XY offset 0, ZW interp mode 0 , Barycentric interp mode 0x1, Point raster rule 0, Multisample mode 0, Multisample Dispatch mode 0
+0x12300f54:      0x00000000:    kernel start pointer 1
+0x12300f58:      0x00000900:    kernel start pointer 2
+0x12300f5c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300f60:      0x00000016:    vertex count
+0x12300f64:      0x00000052:    start vertex
+0x12300f68:      0x00000001:    instance count
+0x12300f6c:      0x00000000:    start instance
+0x12300f70:      0x00000000:    index bias
+0x12300f74:      0x05000000: MI_BATCH_BUFFER_END
diff --git a/intel/tests/gen6-3d.batch.sh b/intel/tests/gen6-3d.batch.sh
new file mode 100644 (file)
index 0000000..a94057f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST_FILENAME=`echo "$0" | sed 's|.sh||'`
+./test_decode $TEST_FILENAME
+
+ret=$?
+
+# pretty-print a diff showing what happened, and leave the dumped
+# around for possibly moving over the ref.
+if test $ret = 1; then
+    REF_FILENAME="$TEST_FILENAME-ref.txt"
+    NEW_FILENAME="$TEST_FILENAME-new.txt"
+    ./test_decode $TEST_FILENAME -dump > $NEW_FILENAME
+    if test $? = 0; then
+       echo "Differences:"
+       diff -u $REF_FILENAME $NEW_FILENAME
+    fi
+fi
+
+exit $ret
diff --git a/intel/tests/gen7-2d-copy.batch b/intel/tests/gen7-2d-copy.batch
new file mode 100644 (file)
index 0000000..ce7fc29
Binary files /dev/null and b/intel/tests/gen7-2d-copy.batch differ
diff --git a/intel/tests/gen7-2d-copy.batch-ref.txt b/intel/tests/gen7-2d-copy.batch-ref.txt
new file mode 100644 (file)
index 0000000..0d621d3
--- /dev/null
@@ -0,0 +1,14 @@
+0x12300000:      0x54f08006: XY_SRC_COPY_BLT (rgb enabled, alpha enabled, src tile 1, dst tile 0)
+0x12300004:      0x03cc0190:    format 8888, pitch 400, rop 0xcc, clipping disabled,  
+0x12300008:      0x00000000:    dst (0,0)
+0x1230000c:      0x00640064:    dst (100,100)
+0x12300010:      0x122e9000:    dst offset 0x122e9000
+0x12300014:      0x00000000:    src (0,0)
+0x12300018:      0x00000080:    src pitch 128
+0x1230001c:      0x02ff1000:    src offset 0x02ff1000
+0x12300020:      0x13000002: MI_FLUSH_DW post_sync_op='no write' 
+0x12300024:      0x00000000:    address
+0x12300028:      0x00000000:    dword
+0x1230002c:      0x00000000:    upper dword
+0x12300030:      0x05000000: MI_BATCH_BUFFER_END
+0x12300034:      0x00000000:    
diff --git a/intel/tests/gen7-2d-copy.batch.sh b/intel/tests/gen7-2d-copy.batch.sh
new file mode 100644 (file)
index 0000000..a94057f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST_FILENAME=`echo "$0" | sed 's|.sh||'`
+./test_decode $TEST_FILENAME
+
+ret=$?
+
+# pretty-print a diff showing what happened, and leave the dumped
+# around for possibly moving over the ref.
+if test $ret = 1; then
+    REF_FILENAME="$TEST_FILENAME-ref.txt"
+    NEW_FILENAME="$TEST_FILENAME-new.txt"
+    ./test_decode $TEST_FILENAME -dump > $NEW_FILENAME
+    if test $? = 0; then
+       echo "Differences:"
+       diff -u $REF_FILENAME $NEW_FILENAME
+    fi
+fi
+
+exit $ret
diff --git a/intel/tests/gen7-3d.batch b/intel/tests/gen7-3d.batch
new file mode 100644 (file)
index 0000000..328ec88
Binary files /dev/null and b/intel/tests/gen7-3d.batch differ
diff --git a/intel/tests/gen7-3d.batch-ref.txt b/intel/tests/gen7-3d.batch-ref.txt
new file mode 100644 (file)
index 0000000..be3c85e
--- /dev/null
@@ -0,0 +1,212 @@
+0x12300000:      0x69040000: 3DSTATE_PIPELINE_SELECT
+0x12300004:      0x790d0002: 3DSTATE_MULTISAMPLE
+0x12300008:      0x00000000:    dword 1
+0x1230000c:      0x00000000:    dword 2
+0x12300010:      0x00000000:    dword 3
+0x12300014:      0x78180000: 3DSTATE_SAMPLE_MASK
+0x12300018:      0x00000001:    dword 1
+0x1230001c:      0x61020000: STATE_SIP
+0x12300020:      0x00000000:    dword 1
+0x12300024:      0x680b0000: 3DSTATE_VF_STATISTICS
+0x12300028:      0x61010008: STATE_BASE_ADDRESS
+0x1230002c:      0x00000001:    general state base address 0x00000000
+0x12300030:      0x091ba001:    surface state base address 0x091ba000
+0x12300034:      0x091ba001:    dynamic state base address 0x091ba000
+0x12300038:      0x00000001:    indirect state base address 0x00000000
+0x1230003c:      0x091c2001:    instruction state base address 0x091c2000
+0x12300040:      0x00000001:    general state upper bound disabled
+0x12300044:      0x091c2001:    dynamic state upper bound 0x091c2000
+0x12300048:      0x00000001:    indirect state upper bound disabled
+0x1230004c:      0x00000001:    instruction state upper bound disabled
+0x12300050:      0x78230000: 3DSTATE_VIEWPORT_STATE_POINTERS_CC
+0x12300054:      0x00007fe0:    pointer to CC viewport
+0x12300058:      0x78210000: 3DSTATE_VIEWPORT_STATE_POINTERS_SF_CLIP
+0x1230005c:      0x00007f80:    pointer to SF_CLIP viewport
+0x12300060:      0x78300000: 3DSTATE_URB_VS
+0x12300064:      0x040002c0:    16KB start, size=1 64B rows, nr_entries=704, total size 45056B
+0x12300068:      0x78330000: 3DSTATE_URB_GS
+0x1230006c:      0x04000000:    16KB start, size=1 64B rows, nr_entries=0, total size 0B
+0x12300070:      0x78310000: 3DSTATE_URB_HS
+0x12300074:      0x04000000:    16KB start, size=1 64B rows, nr_entries=0, total size 0B
+0x12300078:      0x78320000: 3DSTATE_URB_DS
+0x1230007c:      0x04000000:    16KB start, size=1 64B rows, nr_entries=0, total size 0B
+0x12300080:      0x78240000: 3DSTATE_BLEND_STATE_POINTERS
+0x12300084:      0x00007f41:    pointer to BLEND_STATE at 0x00007f40 (changed)
+0x12300088:      0x780e0000: 3DSTATE_CC_STATE_POINTERS
+0x1230008c:      0x00007f01:    pointer to COLOR_CALC_STATE at 0x00007f00 (changed)
+0x12300090:      0x78250000: 3DSTATE_DEPTH_STENCIL_STATE_POINTERS
+0x12300094:      0x00007ec1:    pointer to DEPTH_STENCIL_STATE at 0x00007ec0 (changed)
+0x12300098:      0x78160005: 3DSTATE_CONSTANT_GS
+0x1230009c:      0x00000000:    len 0 = 0, len 1 = 0
+0x123000a0:      0x00000000:    len 2 = 0, len 3 = 0
+0x123000a4:      0x00000000:    pointer to constbuf 0
+0x123000a8:      0x00000000:    pointer to constbuf 1
+0x123000ac:      0x00000000:    pointer to constbuf 2
+0x123000b0:      0x00000000:    pointer to constbuf 3
+0x123000b4:      0x78110005: 3DSTATE_GS
+0x123000b8:      0x00000000:    kernel pointer
+0x123000bc:      0x00000000:    SPF=0, VME=0, Sampler Count 0, Binding table count 0
+0x123000c0:      0x00000000:    scratch offset
+0x123000c4:      0x00000401:    Dispatch GRF start 1, VUE read length 0, VUE read offset 0
+0x123000c8:      0x00000400:    Max Threads 1, Rendering disable
+0x123000cc:      0x00000000:    Reorder disable, Discard Adjaceny disable, GS disable
+0x123000d0:      0x78290000: 3DSTATE_BINDING_TABLE_POINTERS_GS
+0x123000d4:      0x00000000:    dword 1
+0x123000d8:      0x78190005: 3DSTATE_CONSTANT_HS
+0x123000dc:      0x00000000:    len 0 = 0, len 1 = 0
+0x123000e0:      0x00000000:    len 2 = 0, len 3 = 0
+0x123000e4:      0x00000000:    pointer to constbuf 0
+0x123000e8:      0x00000000:    pointer to constbuf 1
+0x123000ec:      0x00000000:    pointer to constbuf 2
+0x123000f0:      0x00000000:    pointer to constbuf 3
+0x123000f4:      0x781b0005: 3DSTATE_HS
+0x123000f8:      0x00000000:    dword 1
+0x123000fc:      0x00000000:    dword 2
+0x12300100:      0x00000000:    dword 3
+0x12300104:      0x00000000:    dword 4
+0x12300108:      0x00000000:    dword 5
+0x1230010c:      0x00000000:    dword 6
+0x12300110:      0x78270000: 3DSTATE_BINDING_TABLE_POINTERS_HS
+0x12300114:      0x00000000:    dword 1
+0x12300118:      0x781c0002: 3DSTATE_TE
+0x1230011c:      0x00000000:    dword 1
+0x12300120:      0x00000000:    dword 2
+0x12300124:      0x00000000:    dword 3
+0x12300128:      0x781a0005: 3DSTATE_CONSTANT_DS
+0x1230012c:      0x00000000:    len 0 = 0, len 1 = 0
+0x12300130:      0x00000000:    len 2 = 0, len 3 = 0
+0x12300134:      0x00000000:    pointer to constbuf 0
+0x12300138:      0x00000000:    pointer to constbuf 1
+0x1230013c:      0x00000000:    pointer to constbuf 2
+0x12300140:      0x00000000:    pointer to constbuf 3
+0x12300144:      0x781d0004: 3DSTATE_DS
+0x12300148:      0x00000000:    dword 1
+0x1230014c:      0x00000000:    dword 2
+0x12300150:      0x00000000:    dword 3
+0x12300154:      0x00000000:    dword 4
+0x12300158:      0x00000000:    dword 5
+0x1230015c:      0x78280000: 3DSTATE_BINDING_TABLE_POINTERS_DS
+0x12300160:      0x00000000:    dword 1
+0x12300164:      0x78260000: 3DSTATE_BINDING_TABLE_POINTERS_VS
+0x12300168:      0x00007c40:    dword 1
+0x1230016c:      0x782b0000: 3DSTATE_SAMPLER_STATE_POINTERS_VS
+0x12300170:      0x00007c20:    dword 1
+0x12300174:      0x79120000: 3DSTATE_PUSH_CONSTANT_ALLOC_VS
+0x12300178:      0x00000008:    dword 1
+0x1230017c:      0x78150005: 3DSTATE_CONSTANT_VS
+0x12300180:      0x00000002:    len 0 = 2, len 1 = 0
+0x12300184:      0x00000000:    len 2 = 0, len 3 = 0
+0x12300188:      0x00007e00:    pointer to constbuf 0
+0x1230018c:      0x00000000:    pointer to constbuf 1
+0x12300190:      0x00000000:    pointer to constbuf 2
+0x12300194:      0x00000000:    pointer to constbuf 3
+0x12300198:      0x78100004: 3DSTATE_VS
+0x1230019c:      0x00000000:    kernel pointer
+0x123001a0:      0x08000000:    SPF=0, VME=0, Sampler Count 1, Binding table count 0
+0x123001a4:      0x00000000:    scratch offset
+0x123001a8:      0x00100800:    Dispatch GRF start 1, VUE read length 1, VUE read offset 0
+0x123001ac:      0xfe000401:    Max Threads 128, Vertex Cache enable, VS func enable
+0x123001b0:      0x781e0001: 3DSTATE_STREAMOUT
+0x123001b4:      0x00000000:    dword 1
+0x123001b8:      0x00000000:    dword 2
+0x123001bc:      0x78120002: 3DSTATE_CLIP
+0x123001c0:      0x00150400:    UserClip distance cull test mask 0x0
+0x123001c4:      0x98000026:    Clip enable, API mode OGL, Viewport XY test enable, Viewport Z test enable, Guardband test disable, Clip mode 0, Perspective Divide enable, Non-Perspective Barycentric disable, Tri Provoking 2, Line Provoking 1, Trifan Provoking 2
+0x123001c8:      0x0003ffe0:    Min PointWidth 1, Max PointWidth 2047, Force Zero RTAIndex enable, Max VPIndex 0
+0x123001cc:      0x781f000c: 3DSTATE_SBE
+0x123001d0:      0x00600810:    dword 1
+0x123001d4:      0x00000000:    dword 2
+0x123001d8:      0x00000000:    dword 3
+0x123001dc:      0x00000000:    dword 4
+0x123001e0:      0x00000000:    dword 5
+0x123001e4:      0x00000000:    dword 6
+0x123001e8:      0x00000000:    dword 7
+0x123001ec:      0x00000000:    dword 8
+0x123001f0:      0x00000000:    dword 9
+0x123001f4:      0x00000000:    dword 10
+0x123001f8:      0x00000000:    dword 11
+0x123001fc:      0x00000000:    dword 12
+0x12300200:      0x00000000:    dword 13
+0x12300204:      0x78130005: 3DSTATE_SF
+0x12300208:      0x00001403:    dword 1
+0x1230020c:      0x22000000:    dword 2
+0x12300210:      0x4c000808:    dword 3
+0x12300214:      0x00000000:    dword 4
+0x12300218:      0x00000000:    dword 5
+0x1230021c:      0x00000000:    dword 6
+0x12300220:      0x78140001: 3DSTATE_WM
+0x12300224:      0xa0000840:    (PP ), point UR
+0x12300228:      0x00000000:    MS
+0x1230022c:      0x782a0000: 3DSTATE_BINDING_TABLE_POINTERS_PS
+0x12300230:      0x00007c40:    dword 1
+0x12300234:      0x782f0000: 3DSTATE_SAMPLER_STATE_POINTERS_PS
+0x12300238:      0x00007c20:    dword 1
+0x1230023c:      0x79160000: 3DSTATE_PUSH_CONSTANT_ALLOC_PS
+0x12300240:      0x00080008:    dword 1
+0x12300244:      0x78170005: 3DSTATE_CONSTANT_PS
+0x12300248:      0x00000000:    len 0 = 0, len 1 = 0
+0x1230024c:      0x00000000:    len 2 = 0, len 3 = 0
+0x12300250:      0x00000000:    pointer to constbuf 0
+0x12300254:      0x00000000:    pointer to constbuf 1
+0x12300258:      0x00000000:    pointer to constbuf 2
+0x1230025c:      0x00000000:    pointer to constbuf 3
+0x12300260:      0x78200006: 3DSTATE_PS
+0x12300264:      0x00000140:    dword 1
+0x12300268:      0x08000000:    dword 2
+0x1230026c:      0x00000000:    dword 3
+0x12300270:      0x55000403:    dword 4
+0x12300274:      0x00040006:    dword 5
+0x12300278:      0x00000000:    dword 6
+0x1230027c:      0x00000240:    dword 7
+0x12300280:      0x780f0000: 3DSTATE_SCISSOR_POINTERS
+0x12300284:      0x00007be0:    scissor rect offset
+0x12300288:      0x7a000002: PIPE_CONTROL
+0x1230028c:      0x00002000:    no write, depth stall, 
+0x12300290:      0x00000000:    
+0x12300294:      0x00000000:    
+0x12300298:      0x7a000002: PIPE_CONTROL
+0x1230029c:      0x00000001:    no write, depth cache flush, 
+0x123002a0:      0x00000000:    
+0x123002a4:      0x00000000:    
+0x123002a8:      0x7a000002: PIPE_CONTROL
+0x123002ac:      0x00002000:    no write, depth stall, 
+0x123002b0:      0x00000000:    
+0x123002b4:      0x00000000:    
+0x123002b8:      0x78050005: 3DSTATE_DEPTH_BUFFER
+0x123002bc:      0xe0040000:    dword 1
+0x123002c0:      0x00000000:    dword 2
+0x123002c4:      0x00000000:    dword 3
+0x123002c8:      0x00000000:    dword 4
+0x123002cc:      0x00000000:    dword 5
+0x123002d0:      0x00000000:    dword 6
+0x123002d4:      0x78070001: 3DSTATE_HIER_DEPTH_BUFFER
+0x123002d8:      0x00000000:    pitch 1b
+0x123002dc:      0x00000000:    pointer to HiZ buffer
+0x123002e0:      0x78060001: 3DSTATE_STENCIL_BUFFER
+0x123002e4:      0x00000000:    dword 1
+0x123002e8:      0x00000000:    dword 2
+0x123002ec:      0x78040001: 3DSTATE_CLEAR_PARAMS
+0x123002f0:      0x00000000:    dword 1
+0x123002f4:      0x00000000:    dword 2
+0x123002f8:      0x79000002: 3DSTATE_DRAWING_RECTANGLE
+0x123002fc:      0x00000000:    top left: 0,0
+0x12300300:      0x00130077:    bottom right: 119,19
+0x12300304:      0x00000000:    origin: 0,0
+0x12300308:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x1230030c:      0x00004014:    buffer 0: sequential, pitch 20b
+0x12300310:      0x158b3000:    buffer address
+0x12300314:      0x158c2fff:    max index
+0x12300318:      0x00000000:    mbz
+0x1230031c:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x12300320:      0x02850000:    buffer 0: invalid, type 0x0085, src offset 0x0000 bytes
+0x12300324:      0x11230000:    (X, Y, 0.0, 1.0), dst offset 0x00 bytes
+0x12300328:      0x02400008:    buffer 0: invalid, type 0x0040, src offset 0x0008 bytes
+0x1230032c:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300330:      0x7b000005: 3DPRIMITIVE: 
+0x12300334:      0x00000007:    quad list sequential
+0x12300338:      0x00000004:    vertex count
+0x1230033c:      0x00000000:    start vertex
+0x12300340:      0x00000001:    instance count
+0x12300344:      0x00000000:    start instance
+0x12300348:      0x00000000:    index bias
+0x1230034c:      0x05000000: MI_BATCH_BUFFER_END
diff --git a/intel/tests/gen7-3d.batch.sh b/intel/tests/gen7-3d.batch.sh
new file mode 100644 (file)
index 0000000..a94057f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST_FILENAME=`echo "$0" | sed 's|.sh||'`
+./test_decode $TEST_FILENAME
+
+ret=$?
+
+# pretty-print a diff showing what happened, and leave the dumped
+# around for possibly moving over the ref.
+if test $ret = 1; then
+    REF_FILENAME="$TEST_FILENAME-ref.txt"
+    NEW_FILENAME="$TEST_FILENAME-new.txt"
+    ./test_decode $TEST_FILENAME -dump > $NEW_FILENAME
+    if test $? = 0; then
+       echo "Differences:"
+       diff -u $REF_FILENAME $NEW_FILENAME
+    fi
+fi
+
+exit $ret
diff --git a/intel/tests/gm45-3d.batch b/intel/tests/gm45-3d.batch
new file mode 100644 (file)
index 0000000..549608b
Binary files /dev/null and b/intel/tests/gm45-3d.batch differ
diff --git a/intel/tests/gm45-3d.batch-ref.txt b/intel/tests/gm45-3d.batch-ref.txt
new file mode 100644 (file)
index 0000000..5a47d77
--- /dev/null
@@ -0,0 +1,488 @@
+0x12300000:      0x69040000: 3DSTATE_PIPELINE_SELECT
+0x12300004:      0x79090000: 3DSTATE_GLOBAL_DEPTH_OFFSET_CLAMP
+0x12300008:      0x00000000:    dword 1
+0x1230000c:      0x61020000: STATE_SIP
+0x12300010:      0x00000000:    dword 1
+0x12300014:      0x680b0000: 3DSTATE_VF_STATISTICS
+0x12300018:      0x61010004: STATE_BASE_ADDRESS
+0x1230001c:      0x00000001:    general state base address 0x00000000
+0x12300020:      0x00000001:    surface state base address 0x00000000
+0x12300024:      0x00000001:    indirect state base address 0x00000000
+0x12300028:      0x00000001:    general state upper bound disabled
+0x1230002c:      0x00000001:    indirect state upper bound disabled
+0x12300030:      0x78010004: 3DSTATE_BINDING_TABLE_POINTERS
+0x12300034:      0x00007e20:    VS binding table
+0x12300038:      0x00000000:    GS binding table
+0x1230003c:      0x00000000:    Clip binding table
+0x12300040:      0x00000000:    SF binding table
+0x12300044:      0x00007e20:    WM binding table
+0x12300048:      0x79010003: 3DSTATE_CONSTANT_COLOR
+0x1230004c:      0x00000000:    dword 1
+0x12300050:      0x00000000:    dword 2
+0x12300054:      0x00000000:    dword 3
+0x12300058:      0x00000000:    dword 4
+0x1230005c:      0x79050004: 3DSTATE_DEPTH_BUFFER
+0x12300060:      0x2c0805ff:    2D, z24s8, pitch = 1536 bytes, tiled
+0x12300064:      0x00000000:    depth offset
+0x12300068:      0x09584ac0:    300x300
+0x1230006c:      0x00000000:    volume depth
+0x12300070:      0x00000000:    
+0x12300074:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300078:      0x00007d60:    VS state
+0x1230007c:      0x00000000:    GS state
+0x12300080:      0x00007d21:    Clip state
+0x12300084:      0x00007d80:    SF state
+0x12300088:      0x00007de0:    WM state
+0x1230008c:      0x00007fc0:    CC state
+0x12300090:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300094:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300098:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230009c:      0x60010000: CS_URB_STATE
+0x123000a0:      0x00000024:    entry_size: 2 [192 bytes], n_entries: 4
+0x123000a4:      0x79000002: 3DSTATE_DRAWING_RECTANGLE
+0x123000a8:      0x00000000:    top left: 0,0
+0x123000ac:      0x012b012b:    bottom right: 299,299
+0x123000b0:      0x00000000:    origin: 0,0
+0x123000b4:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123000b8:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x123000bc:      0x00000000:    buffer address
+0x123000c0:      0x00000000:    max index
+0x123000c4:      0x00000000:    mbz
+0x123000c8:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123000cc:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123000d0:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123000d4:      0x60020100: CONSTANT_BUFFER: valid
+0x123000d8:      0x00000001:    offset: 0x00000000, length: 128 bytes
+0x123000dc:      0x7b001804: 3DPRIMITIVE: tri fan sequential
+0x123000e0:      0x00000004:    vertex count
+0x123000e4:      0x00000000:    start vertex
+0x123000e8:      0x00000001:    instance count
+0x123000ec:      0x00000000:    start instance
+0x123000f0:      0x00000000:    index bias
+0x123000f4:      0x78010004: 3DSTATE_BINDING_TABLE_POINTERS
+0x123000f8:      0x00007b40:    VS binding table
+0x123000fc:      0x00000000:    GS binding table
+0x12300100:      0x00000000:    Clip binding table
+0x12300104:      0x00000000:    SF binding table
+0x12300108:      0x00007b40:    WM binding table
+0x1230010c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300110:      0x00007aa0:    VS state
+0x12300114:      0x00007a41:    GS state
+0x12300118:      0x00007a61:    Clip state
+0x1230011c:      0x00007ac0:    SF state
+0x12300120:      0x00007b00:    WM state
+0x12300124:      0x00007cc0:    CC state
+0x12300128:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230012c:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300130:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x12300134:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300138:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x1230013c:      0x00000000:    buffer address
+0x12300140:      0x00000000:    max index
+0x12300144:      0x00000000:    mbz
+0x12300148:      0x60020100: CONSTANT_BUFFER: valid
+0x1230014c:      0x00000082:    offset: 0x00000080, length: 192 bytes
+0x12300150:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300154:      0x00000052:    vertex count
+0x12300158:      0x00000000:    start vertex
+0x1230015c:      0x00000001:    instance count
+0x12300160:      0x00000000:    start instance
+0x12300164:      0x00000000:    index bias
+0x12300168:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x1230016c:      0x00007aa0:    VS state
+0x12300170:      0x00007a21:    GS state
+0x12300174:      0x00007a61:    Clip state
+0x12300178:      0x00007ac0:    SF state
+0x1230017c:      0x00007b00:    WM state
+0x12300180:      0x00007cc0:    CC state
+0x12300184:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300188:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x1230018c:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x12300190:      0x60020100: CONSTANT_BUFFER: valid
+0x12300194:      0x00000082:    offset: 0x00000080, length: 192 bytes
+0x12300198:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x1230019c:      0x00000050:    vertex count
+0x123001a0:      0x00000052:    start vertex
+0x123001a4:      0x00000001:    instance count
+0x123001a8:      0x00000000:    start instance
+0x123001ac:      0x00000000:    index bias
+0x123001b0:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123001b4:      0x00007aa0:    VS state
+0x123001b8:      0x00007a01:    GS state
+0x123001bc:      0x00007a61:    Clip state
+0x123001c0:      0x00007ac0:    SF state
+0x123001c4:      0x00007b00:    WM state
+0x123001c8:      0x00007cc0:    CC state
+0x123001cc:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123001d0:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x123001d4:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x123001d8:      0x60020100: CONSTANT_BUFFER: valid
+0x123001dc:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x123001e0:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123001e4:      0x00000052:    vertex count
+0x123001e8:      0x000000a2:    start vertex
+0x123001ec:      0x00000001:    instance count
+0x123001f0:      0x00000000:    start instance
+0x123001f4:      0x00000000:    index bias
+0x123001f8:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123001fc:      0x00007aa0:    VS state
+0x12300200:      0x000079e1:    GS state
+0x12300204:      0x00007a61:    Clip state
+0x12300208:      0x00007ac0:    SF state
+0x1230020c:      0x00007b00:    WM state
+0x12300210:      0x00007cc0:    CC state
+0x12300214:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300218:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x1230021c:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x12300220:      0x60020100: CONSTANT_BUFFER: valid
+0x12300224:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x12300228:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x1230022c:      0x00000050:    vertex count
+0x12300230:      0x000000f4:    start vertex
+0x12300234:      0x00000001:    instance count
+0x12300238:      0x00000000:    start instance
+0x1230023c:      0x00000000:    index bias
+0x12300240:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300244:      0x00007aa0:    VS state
+0x12300248:      0x000079c1:    GS state
+0x1230024c:      0x00007a61:    Clip state
+0x12300250:      0x00007ac0:    SF state
+0x12300254:      0x00007b00:    WM state
+0x12300258:      0x00007cc0:    CC state
+0x1230025c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300260:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300264:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x12300268:      0x60020100: CONSTANT_BUFFER: valid
+0x1230026c:      0x00000142:    offset: 0x00000140, length: 192 bytes
+0x12300270:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300274:      0x000079a0:    VS state
+0x12300278:      0x000079c1:    GS state
+0x1230027c:      0x00007a61:    Clip state
+0x12300280:      0x00007ac0:    SF state
+0x12300284:      0x00007b00:    WM state
+0x12300288:      0x00007cc0:    CC state
+0x1230028c:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300290:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300294:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x12300298:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x1230029c:      0x00000018:    buffer 0: sequential, pitch 24b
+0x123002a0:      0x00000f48:    buffer address
+0x123002a4:      0x00000000:    max index
+0x123002a8:      0x00000000:    mbz
+0x123002ac:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x123002b0:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123002b4:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123002b8:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x123002bc:      0x11130004:    (X, Y, Z, 1.0), dst offset 0x10 bytes
+0x123002c0:      0x60020100: CONSTANT_BUFFER: valid
+0x123002c4:      0x00000202:    offset: 0x00000200, length: 192 bytes
+0x123002c8:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123002cc:      0x000000a2:    vertex count
+0x123002d0:      0x00000000:    start vertex
+0x123002d4:      0x00000001:    instance count
+0x123002d8:      0x00000000:    start instance
+0x123002dc:      0x00000000:    index bias
+0x123002e0:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123002e4:      0x000079a0:    VS state
+0x123002e8:      0x00000000:    GS state
+0x123002ec:      0x00007901:    Clip state
+0x123002f0:      0x00007940:    SF state
+0x123002f4:      0x00007960:    WM state
+0x123002f8:      0x00007cc0:    CC state
+0x123002fc:      0x00000000: MI_NOOP
+0x12300300:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300304:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300308:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230030c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300310:      0x00000202:    offset: 0x00000200, length: 192 bytes
+0x12300314:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x12300318:      0x0000002a:    vertex count
+0x1230031c:      0x000000a2:    start vertex
+0x12300320:      0x00000001:    instance count
+0x12300324:      0x00000000:    start instance
+0x12300328:      0x00000000:    index bias
+0x1230032c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300330:      0x00007860:    VS state
+0x12300334:      0x00007801:    GS state
+0x12300338:      0x00007821:    Clip state
+0x1230033c:      0x00007880:    SF state
+0x12300340:      0x000078a0:    WM state
+0x12300344:      0x00007cc0:    CC state
+0x12300348:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230034c:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300350:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x12300354:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300358:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x1230035c:      0x00002268:    buffer address
+0x12300360:      0x00000000:    max index
+0x12300364:      0x00000000:    mbz
+0x12300368:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x1230036c:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300370:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x12300374:      0x60020100: CONSTANT_BUFFER: valid
+0x12300378:      0x000002c2:    offset: 0x000002c0, length: 192 bytes
+0x1230037c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300380:      0x0000002a:    vertex count
+0x12300384:      0x00000000:    start vertex
+0x12300388:      0x00000001:    instance count
+0x1230038c:      0x00000000:    start instance
+0x12300390:      0x00000000:    index bias
+0x12300394:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300398:      0x00007860:    VS state
+0x1230039c:      0x000077e1:    GS state
+0x123003a0:      0x00007821:    Clip state
+0x123003a4:      0x00007880:    SF state
+0x123003a8:      0x000078a0:    WM state
+0x123003ac:      0x00007cc0:    CC state
+0x123003b0:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123003b4:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x123003b8:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x123003bc:      0x60020100: CONSTANT_BUFFER: valid
+0x123003c0:      0x000002c2:    offset: 0x000002c0, length: 192 bytes
+0x123003c4:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x123003c8:      0x00000028:    vertex count
+0x123003cc:      0x0000002a:    start vertex
+0x123003d0:      0x00000001:    instance count
+0x123003d4:      0x00000000:    start instance
+0x123003d8:      0x00000000:    index bias
+0x123003dc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123003e0:      0x00007860:    VS state
+0x123003e4:      0x000077c1:    GS state
+0x123003e8:      0x00007821:    Clip state
+0x123003ec:      0x00007880:    SF state
+0x123003f0:      0x000078a0:    WM state
+0x123003f4:      0x00007cc0:    CC state
+0x123003f8:      0x00000000: MI_NOOP
+0x123003fc:      0x00000000: MI_NOOP
+0x12300400:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300404:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300408:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230040c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300410:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x12300414:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300418:      0x0000002a:    vertex count
+0x1230041c:      0x00000052:    start vertex
+0x12300420:      0x00000001:    instance count
+0x12300424:      0x00000000:    start instance
+0x12300428:      0x00000000:    index bias
+0x1230042c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300430:      0x00007860:    VS state
+0x12300434:      0x000077a1:    GS state
+0x12300438:      0x00007821:    Clip state
+0x1230043c:      0x00007880:    SF state
+0x12300440:      0x000078a0:    WM state
+0x12300444:      0x00007cc0:    CC state
+0x12300448:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x1230044c:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300450:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x12300454:      0x60020100: CONSTANT_BUFFER: valid
+0x12300458:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x1230045c:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300460:      0x00000028:    vertex count
+0x12300464:      0x0000007c:    start vertex
+0x12300468:      0x00000001:    instance count
+0x1230046c:      0x00000000:    start instance
+0x12300470:      0x00000000:    index bias
+0x12300474:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300478:      0x00007860:    VS state
+0x1230047c:      0x00007781:    GS state
+0x12300480:      0x00007821:    Clip state
+0x12300484:      0x00007880:    SF state
+0x12300488:      0x000078a0:    WM state
+0x1230048c:      0x00007cc0:    CC state
+0x12300490:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300494:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300498:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230049c:      0x60020100: CONSTANT_BUFFER: valid
+0x123004a0:      0x00000382:    offset: 0x00000380, length: 192 bytes
+0x123004a4:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123004a8:      0x00007760:    VS state
+0x123004ac:      0x00007781:    GS state
+0x123004b0:      0x00007821:    Clip state
+0x123004b4:      0x00007880:    SF state
+0x123004b8:      0x000078a0:    WM state
+0x123004bc:      0x00007cc0:    CC state
+0x123004c0:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123004c4:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x123004c8:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x123004cc:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x123004d0:      0x00000018:    buffer 0: sequential, pitch 24b
+0x123004d4:      0x00002a30:    buffer address
+0x123004d8:      0x00000000:    max index
+0x123004dc:      0x00000000:    mbz
+0x123004e0:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x123004e4:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123004e8:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123004ec:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x123004f0:      0x11130004:    (X, Y, Z, 1.0), dst offset 0x10 bytes
+0x123004f4:      0x60020100: CONSTANT_BUFFER: valid
+0x123004f8:      0x00000442:    offset: 0x00000440, length: 192 bytes
+0x123004fc:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300500:      0x00000052:    vertex count
+0x12300504:      0x00000000:    start vertex
+0x12300508:      0x00000001:    instance count
+0x1230050c:      0x00000000:    start instance
+0x12300510:      0x00000000:    index bias
+0x12300514:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300518:      0x00007760:    VS state
+0x1230051c:      0x00000000:    GS state
+0x12300520:      0x000076c1:    Clip state
+0x12300524:      0x00007700:    SF state
+0x12300528:      0x00007720:    WM state
+0x1230052c:      0x00007cc0:    CC state
+0x12300530:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300534:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300538:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230053c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300540:      0x00000442:    offset: 0x00000440, length: 192 bytes
+0x12300544:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x12300548:      0x00000016:    vertex count
+0x1230054c:      0x00000052:    start vertex
+0x12300550:      0x00000001:    instance count
+0x12300554:      0x00000000:    start instance
+0x12300558:      0x00000000:    index bias
+0x1230055c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300560:      0x00007620:    VS state
+0x12300564:      0x000075c1:    GS state
+0x12300568:      0x000075e1:    Clip state
+0x1230056c:      0x00007640:    SF state
+0x12300570:      0x00007660:    WM state
+0x12300574:      0x00007cc0:    CC state
+0x12300578:      0x00000000: MI_NOOP
+0x1230057c:      0x00000000: MI_NOOP
+0x12300580:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300584:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300588:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230058c:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300590:      0x0000000c:    buffer 0: sequential, pitch 12b
+0x12300594:      0x000033f0:    buffer address
+0x12300598:      0x00000000:    max index
+0x1230059c:      0x00000000:    mbz
+0x123005a0:      0x78090001: 3DSTATE_VERTEX_ELEMENTS
+0x123005a4:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x123005a8:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x123005ac:      0x60020100: CONSTANT_BUFFER: valid
+0x123005b0:      0x00000502:    offset: 0x00000500, length: 192 bytes
+0x123005b4:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x123005b8:      0x0000002a:    vertex count
+0x123005bc:      0x00000000:    start vertex
+0x123005c0:      0x00000001:    instance count
+0x123005c4:      0x00000000:    start instance
+0x123005c8:      0x00000000:    index bias
+0x123005cc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123005d0:      0x00007620:    VS state
+0x123005d4:      0x000075a1:    GS state
+0x123005d8:      0x000075e1:    Clip state
+0x123005dc:      0x00007640:    SF state
+0x123005e0:      0x00007660:    WM state
+0x123005e4:      0x00007cc0:    CC state
+0x123005e8:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123005ec:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x123005f0:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x123005f4:      0x60020100: CONSTANT_BUFFER: valid
+0x123005f8:      0x00000502:    offset: 0x00000500, length: 192 bytes
+0x123005fc:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300600:      0x00000028:    vertex count
+0x12300604:      0x0000002a:    start vertex
+0x12300608:      0x00000001:    instance count
+0x1230060c:      0x00000000:    start instance
+0x12300610:      0x00000000:    index bias
+0x12300614:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300618:      0x00007620:    VS state
+0x1230061c:      0x00007581:    GS state
+0x12300620:      0x000075e1:    Clip state
+0x12300624:      0x00007640:    SF state
+0x12300628:      0x00007660:    WM state
+0x1230062c:      0x00007cc0:    CC state
+0x12300630:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300634:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300638:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230063c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300640:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x12300644:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300648:      0x0000002a:    vertex count
+0x1230064c:      0x00000052:    start vertex
+0x12300650:      0x00000001:    instance count
+0x12300654:      0x00000000:    start instance
+0x12300658:      0x00000000:    index bias
+0x1230065c:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300660:      0x00007620:    VS state
+0x12300664:      0x00007561:    GS state
+0x12300668:      0x000075e1:    Clip state
+0x1230066c:      0x00007640:    SF state
+0x12300670:      0x00007660:    WM state
+0x12300674:      0x00007cc0:    CC state
+0x12300678:      0x00000000: MI_NOOP
+0x1230067c:      0x00000000: MI_NOOP
+0x12300680:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300684:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300688:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230068c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300690:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x12300694:      0x7b001c04: 3DPRIMITIVE: quad list sequential
+0x12300698:      0x00000028:    vertex count
+0x1230069c:      0x0000007c:    start vertex
+0x123006a0:      0x00000001:    instance count
+0x123006a4:      0x00000000:    start instance
+0x123006a8:      0x00000000:    index bias
+0x123006ac:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123006b0:      0x00007620:    VS state
+0x123006b4:      0x00007541:    GS state
+0x123006b8:      0x000075e1:    Clip state
+0x123006bc:      0x00007640:    SF state
+0x123006c0:      0x00007660:    WM state
+0x123006c4:      0x00007cc0:    CC state
+0x123006c8:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x123006cc:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x123006d0:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x123006d4:      0x60020100: CONSTANT_BUFFER: valid
+0x123006d8:      0x000005c2:    offset: 0x000005c0, length: 192 bytes
+0x123006dc:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x123006e0:      0x00007520:    VS state
+0x123006e4:      0x00007541:    GS state
+0x123006e8:      0x000075e1:    Clip state
+0x123006ec:      0x00007640:    SF state
+0x123006f0:      0x00007660:    WM state
+0x123006f4:      0x00007cc0:    CC state
+0x123006f8:      0x00000000: MI_NOOP
+0x123006fc:      0x00000000: MI_NOOP
+0x12300700:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300704:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300708:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230070c:      0x78080003: 3DSTATE_VERTEX_BUFFERS
+0x12300710:      0x00000018:    buffer 0: sequential, pitch 24b
+0x12300714:      0x00003bb8:    buffer address
+0x12300718:      0x00000000:    max index
+0x1230071c:      0x00000000:    mbz
+0x12300720:      0x78090003: 3DSTATE_VERTEX_ELEMENTS
+0x12300724:      0x04400000:    buffer 0: valid, type 0x0040, src offset 0x0000 bytes
+0x12300728:      0x11130000:    (X, Y, Z, 1.0), dst offset 0x00 bytes
+0x1230072c:      0x0440000c:    buffer 0: valid, type 0x0040, src offset 0x000c bytes
+0x12300730:      0x11130004:    (X, Y, Z, 1.0), dst offset 0x10 bytes
+0x12300734:      0x60020100: CONSTANT_BUFFER: valid
+0x12300738:      0x00000682:    offset: 0x00000680, length: 192 bytes
+0x1230073c:      0x7b002004: 3DPRIMITIVE: quad strip sequential
+0x12300740:      0x00000052:    vertex count
+0x12300744:      0x00000000:    start vertex
+0x12300748:      0x00000001:    instance count
+0x1230074c:      0x00000000:    start instance
+0x12300750:      0x00000000:    index bias
+0x12300754:      0x78000005: 3DSTATE_PIPELINED_POINTERS
+0x12300758:      0x00007520:    VS state
+0x1230075c:      0x00000000:    GS state
+0x12300760:      0x00007481:    Clip state
+0x12300764:      0x000074c0:    SF state
+0x12300768:      0x000074e0:    WM state
+0x1230076c:      0x00007cc0:    CC state
+0x12300770:      0x60003f01: URB_FENCE: cs vfe sf clip gs vs 
+0x12300774:      0x05212040:    vs fence: 64, clip_fence: 82, gs_fence: 72
+0x12300778:      0x18000062:    sf fence: 98, vfe_fence: 0, cs_fence: 384
+0x1230077c:      0x60020100: CONSTANT_BUFFER: valid
+0x12300780:      0x00000682:    offset: 0x00000680, length: 192 bytes
+0x12300784:      0x7b001404: 3DPRIMITIVE: tri strip sequential
+0x12300788:      0x00000016:    vertex count
+0x1230078c:      0x00000052:    start vertex
+0x12300790:      0x00000001:    instance count
+0x12300794:      0x00000000:    start instance
+0x12300798:      0x00000000:    index bias
+0x1230079c:      0x05000000: MI_BATCH_BUFFER_END
diff --git a/intel/tests/gm45-3d.batch.sh b/intel/tests/gm45-3d.batch.sh
new file mode 100644 (file)
index 0000000..a94057f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST_FILENAME=`echo "$0" | sed 's|.sh||'`
+./test_decode $TEST_FILENAME
+
+ret=$?
+
+# pretty-print a diff showing what happened, and leave the dumped
+# around for possibly moving over the ref.
+if test $ret = 1; then
+    REF_FILENAME="$TEST_FILENAME-ref.txt"
+    NEW_FILENAME="$TEST_FILENAME-new.txt"
+    ./test_decode $TEST_FILENAME -dump > $NEW_FILENAME
+    if test $? = 0; then
+       echo "Differences:"
+       diff -u $REF_FILENAME $NEW_FILENAME
+    fi
+fi
+
+exit $ret
diff --git a/intel/tests/test-batch.sh b/intel/tests/test-batch.sh
new file mode 100644 (file)
index 0000000..a94057f
--- /dev/null
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+TEST_FILENAME=`echo "$0" | sed 's|.sh||'`
+./test_decode $TEST_FILENAME
+
+ret=$?
+
+# pretty-print a diff showing what happened, and leave the dumped
+# around for possibly moving over the ref.
+if test $ret = 1; then
+    REF_FILENAME="$TEST_FILENAME-ref.txt"
+    NEW_FILENAME="$TEST_FILENAME-new.txt"
+    ./test_decode $TEST_FILENAME -dump > $NEW_FILENAME
+    if test $? = 0; then
+       echo "Differences:"
+       diff -u $REF_FILENAME $NEW_FILENAME
+    fi
+fi
+
+exit $ret
index b46e2a6..fdd911f 100644 (file)
@@ -7,4 +7,4 @@ Name: libdrm
 Description: Userspace interface to kernel DRM services
 Version: @PACKAGE_VERSION@
 Libs: -L${libdir} -ldrm
-Cflags: -I${includedir} -I${includedir}/libdrm
+Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/exynos
index 6410f57..8926d8d 100644 (file)
@@ -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;                                \
+}
index ad4fd19..df74b7e 100644 (file)
@@ -33,6 +33,7 @@ endif
 
 if HAVE_SLP
 libkms_la_SOURCES += slp.c
+AM_CFLAGS += -I$(top_srcdir)/exynos
 endif
 
 libkmsincludedir = ${includedir}/libkms
old mode 100755 (executable)
new mode 100644 (file)
index 145b4b2..5e2501e 100644 (file)
@@ -74,6 +74,4 @@ int nouveau_create(int fd, struct kms_driver **out);
 
 int radeon_create(int fd, struct kms_driver **out);
 
-int slp_create(int fd, struct kms_driver **out);
-
 #endif
index 75b7cfe..fc4f205 100644 (file)
@@ -115,10 +115,6 @@ linux_from_sysfs(int fd, struct kms_driver **out)
        else if (!strcmp(name, "radeon"))
                ret = radeon_create(fd, out);
 #endif
-#ifdef HAVE_SLP
-       else if (!strcmp(name, "exynos-drm"))
-               ret = slp_create(fd, out);
-#endif
        else
                ret = -ENOSYS;
 
index 8b89916..206e892 100644 (file)
@@ -3,41 +3,23 @@ AM_CFLAGS = \
        -I$(top_srcdir) \
        -I$(top_srcdir)/nouveau \
        $(PTHREADSTUBS_CFLAGS) \
-       -I$(top_srcdir)/include/drm
+       -I$(top_srcdir)/include/drm \
+       -DDEBUG
 
 libdrm_nouveau_la_LTLIBRARIES = libdrm_nouveau.la
 libdrm_nouveau_ladir = $(libdir)
-libdrm_nouveau_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libdrm_nouveau_la_LDFLAGS = -version-number 2:0:0 -no-undefined
 libdrm_nouveau_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
 
-libdrm_nouveau_la_SOURCES = \
-                           nouveau_device.c \
-                           nouveau_channel.c \
-                           nouveau_pushbuf.c \
-                           nouveau_grobj.c \
-                           nouveau_notifier.c \
-                           nouveau_bo.c \
-                           nouveau_resource.c \
-                           nouveau_private.h \
-                           nouveau_reloc.c
-
-libdrm_nouveaucommonincludedir = ${includedir}/nouveau
-libdrm_nouveaucommoninclude_HEADERS = \
-                               nouveau_device.h \
-                               nouveau_channel.h \
-                               nouveau_grobj.h \
-                               nouveau_notifier.h \
-                               nouveau_pushbuf.h \
-                               nv04_pushbuf.h \
-                               nvc0_pushbuf.h \
-                               nouveau_bo.h \
-                               nouveau_resource.h \
-                               nouveau_reloc.h
+libdrm_nouveau_la_SOURCES = nouveau.c \
+                           pushbuf.c \
+                           bufctx.c \
+                           abi16.c \
+                           private.h
 
 
 libdrm_nouveauincludedir = ${includedir}/libdrm
-libdrm_nouveauinclude_HEADERS = \
-                               nouveau_drmif.h
+libdrm_nouveauinclude_HEADERS = nouveau.h
 
 pkgconfigdir = @pkgconfigdir@
 pkgconfig_DATA = libdrm_nouveau.pc
diff --git a/nouveau/abi16.c b/nouveau/abi16.c
new file mode 100644 (file)
index 0000000..69a0a9b
--- /dev/null
@@ -0,0 +1,198 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#include <stdlib.h>
+#include <stdint.h>
+
+#include "private.h"
+
+int
+abi16_chan_nv04(struct nouveau_object *obj)
+{
+       struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
+       struct drm_nouveau_channel_alloc req;
+       struct nv04_fifo *nv04 = obj->data;
+       int ret;
+
+       req.fb_ctxdma_handle = nv04->vram;
+       req.tt_ctxdma_handle = nv04->gart;
+
+       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
+                                 &req, sizeof(req));
+       if (ret)
+               return ret;
+
+       nv04->base.channel = req.channel;
+       nv04->base.pushbuf = req.pushbuf_domains;
+       nv04->notify = req.notifier_handle;
+       nv04->base.object->handle = req.channel;
+       nv04->base.object->length = sizeof(*nv04);
+       return 0;
+}
+
+int
+abi16_chan_nvc0(struct nouveau_object *obj)
+{
+       struct nouveau_device *dev = (struct nouveau_device *)obj->parent;
+       struct drm_nouveau_channel_alloc req = {};
+       struct nvc0_fifo *nvc0 = obj->data;
+       int ret;
+
+       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
+                                 &req, sizeof(req));
+       if (ret)
+               return ret;
+
+       nvc0->base.channel = req.channel;
+       nvc0->base.pushbuf = req.pushbuf_domains;
+       nvc0->notify = req.notifier_handle;
+       nvc0->base.object->handle = req.channel;
+       nvc0->base.object->length = sizeof(*nvc0);
+       return 0;
+}
+
+int
+abi16_engobj(struct nouveau_object *obj)
+{
+       struct drm_nouveau_grobj_alloc req = {
+               obj->parent->handle, obj->handle, obj->oclass
+       };
+       struct nouveau_device *dev;
+       int ret;
+
+       dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+       ret = drmCommandWrite(dev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
+                             &req, sizeof(req));
+       if (ret)
+               return ret;
+
+       obj->length = sizeof(struct nouveau_object *);
+       return 0;
+}
+
+int
+abi16_ntfy(struct nouveau_object *obj)
+{
+       struct nv04_notify *ntfy = obj->data;
+       struct drm_nouveau_notifierobj_alloc req = {
+               obj->parent->handle, ntfy->object->handle, ntfy->length
+       };
+       struct nouveau_device *dev;
+       int ret;
+
+       dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
+                                 &req, sizeof(req));
+       if (ret)
+               return ret;
+
+       ntfy->offset = req.offset;
+       ntfy->object->length = sizeof(*ntfy);
+       return 0;
+}
+
+void
+abi16_bo_info(struct nouveau_bo *bo, struct drm_nouveau_gem_info *info)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+
+       nvbo->map_handle = info->map_handle;
+       bo->handle = info->handle;
+       bo->size = info->size;
+       bo->offset = info->offset;
+
+       bo->flags = 0;
+       if (info->domain & NOUVEAU_GEM_DOMAIN_VRAM)
+               bo->flags |= NOUVEAU_BO_VRAM;
+       if (info->domain & NOUVEAU_GEM_DOMAIN_GART)
+               bo->flags |= NOUVEAU_BO_GART;
+       if (!(info->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG))
+               bo->flags |= NOUVEAU_BO_CONTIG;
+       if (nvbo->map_handle)
+               bo->flags |= NOUVEAU_BO_MAP;
+
+       if (bo->device->chipset >= 0xc0) {
+               bo->config.nvc0.memtype   = (info->tile_flags & 0xff00) >> 8;
+               bo->config.nvc0.tile_mode = info->tile_mode;
+       } else
+       if (bo->device->chipset >= 0x80 || bo->device->chipset == 0x50) {
+               bo->config.nv50.memtype   = (info->tile_flags & 0x07f00) >> 8 |
+                                           (info->tile_flags & 0x30000) >> 9;
+               bo->config.nv50.tile_mode = info->tile_mode << 4;
+       } else {
+               bo->config.nv04.surf_flags = info->tile_flags & 7;
+               bo->config.nv04.surf_pitch = info->tile_mode;
+       }
+}
+
+int
+abi16_bo_init(struct nouveau_bo *bo, uint32_t alignment,
+             union nouveau_bo_config *config)
+{
+       struct nouveau_device *dev = bo->device;
+       struct drm_nouveau_gem_new req = {};
+       struct drm_nouveau_gem_info *info = &req.info;
+       int ret;
+
+       if (bo->flags & NOUVEAU_BO_VRAM)
+               info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
+       if (bo->flags & NOUVEAU_BO_GART)
+               info->domain |= NOUVEAU_GEM_DOMAIN_GART;
+       if (!info->domain)
+               info->domain |= NOUVEAU_GEM_DOMAIN_VRAM |
+                               NOUVEAU_GEM_DOMAIN_GART;
+
+       if (bo->flags & NOUVEAU_BO_MAP)
+               info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
+
+       if (!(bo->flags & NOUVEAU_BO_CONTIG))
+               info->tile_flags = NOUVEAU_GEM_TILE_NONCONTIG;
+
+       info->size = bo->size;
+       req.align = alignment;
+
+       if (config) {
+               if (dev->chipset >= 0xc0) {
+                       info->tile_flags = (config->nvc0.memtype & 0xff) << 8;
+                       info->tile_mode  = config->nvc0.tile_mode;
+               } else
+               if (dev->chipset >= 0x80 || dev->chipset == 0x50) {
+                       info->tile_flags = (config->nv50.memtype & 0x07f) << 8 |
+                                          (config->nv50.memtype & 0x180) << 9;
+                       info->tile_mode  = config->nv50.tile_mode >> 4;
+               } else {
+                       info->tile_flags = config->nv04.surf_flags & 7;
+                       info->tile_mode  = config->nv04.surf_pitch;
+               }
+       }
+
+       if (!nouveau_device(dev)->have_bo_usage)
+               info->tile_flags &= 0x0000ff00;
+
+       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_NEW,
+                                 &req, sizeof(req));
+       if (ret == 0)
+               abi16_bo_info(bo, &req.info);
+       return ret;
+}
diff --git a/nouveau/bufctx.c b/nouveau/bufctx.c
new file mode 100644 (file)
index 0000000..23d6f09
--- /dev/null
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "libdrm_lists.h"
+
+#include "nouveau.h"
+#include "private.h"
+
+struct nouveau_bufref_priv {
+       struct nouveau_bufref base;
+       struct nouveau_bufref_priv *next;
+       struct nouveau_bufctx *bufctx;
+};
+
+static inline struct nouveau_bufref_priv *
+nouveau_bufref(struct nouveau_bufref *bctx)
+{
+       return (struct nouveau_bufref_priv *)bctx;
+}
+
+struct nouveau_bufbin_priv {
+       struct nouveau_bufref_priv *list;
+       int relocs;
+};
+
+struct nouveau_bufctx_priv {
+       struct nouveau_bufctx base;
+       struct nouveau_bufref_priv *free;
+       int nr_bins;
+       struct nouveau_bufbin_priv bins[];
+};
+
+static inline struct nouveau_bufctx_priv *
+nouveau_bufctx(struct nouveau_bufctx *bctx)
+{
+       return (struct nouveau_bufctx_priv *)bctx;
+}
+
+int
+nouveau_bufctx_new(struct nouveau_client *client, int bins,
+                  struct nouveau_bufctx **pbctx)
+{
+       struct nouveau_bufctx_priv *priv;
+
+       priv = calloc(1, sizeof(*priv) + sizeof(priv->bins[0]) * bins);
+       if (priv) {
+               DRMINITLISTHEAD(&priv->base.head);
+               DRMINITLISTHEAD(&priv->base.pending);
+               DRMINITLISTHEAD(&priv->base.current);
+               priv->base.client = client;
+               priv->nr_bins = bins;
+               *pbctx = &priv->base;
+               return 0;
+       }
+
+       return -ENOMEM;
+}
+
+void
+nouveau_bufctx_del(struct nouveau_bufctx **pbctx)
+{
+       struct nouveau_bufctx_priv *pctx = nouveau_bufctx(*pbctx);
+       struct nouveau_bufref_priv *pref;
+       if (pctx) {
+               while (pctx->nr_bins--)
+                       nouveau_bufctx_reset(&pctx->base, pctx->nr_bins);
+               while ((pref = pctx->free)) {
+                       pctx->free = pref->next;
+                       free(pref);
+               }
+               free(pctx);
+               *pbctx = NULL;
+       }
+}
+
+void
+nouveau_bufctx_reset(struct nouveau_bufctx *bctx, int bin)
+{
+       struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
+       struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
+       struct nouveau_bufref_priv *pref;
+
+       while ((pref = pbin->list)) {
+               DRMLISTDELINIT(&pref->base.thead);
+               pbin->list = pref->next;
+               pref->next = pctx->free;
+               pctx->free = pref;
+       }
+
+       bctx->relocs -= pbin->relocs;
+       pbin->relocs  = 0;
+}
+
+struct nouveau_bufref *
+nouveau_bufctx_refn(struct nouveau_bufctx *bctx, int bin,
+                   struct nouveau_bo *bo, uint32_t flags)
+{
+       struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
+       struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
+       struct nouveau_bufref_priv *pref = pctx->free;
+
+       if (!pref)
+               pref = malloc(sizeof(*pref));
+       else
+               pctx->free = pref->next;
+
+       if (pref) {
+               pref->base.bo = bo;
+               pref->base.flags = flags;
+               pref->base.packet = 0;
+
+               DRMLISTADDTAIL(&pref->base.thead, &bctx->pending);
+               pref->bufctx = bctx;
+               pref->next = pbin->list;
+               pbin->list = pref;
+       }
+
+       return &pref->base;
+}
+
+struct nouveau_bufref *
+nouveau_bufctx_mthd(struct nouveau_bufctx *bctx, int bin, uint32_t packet,
+                   struct nouveau_bo *bo, uint64_t data, uint32_t flags,
+                   uint32_t vor, uint32_t tor)
+{
+       struct nouveau_bufctx_priv *pctx = nouveau_bufctx(bctx);
+       struct nouveau_bufbin_priv *pbin = &pctx->bins[bin];
+       struct nouveau_bufref *bref = nouveau_bufctx_refn(bctx, bin, bo, flags);
+       if (bref) {
+               bref->packet = packet;
+               bref->data = data;
+               bref->vor = vor;
+               bref->tor = tor;
+               pbin->relocs++;
+               bctx->relocs++;
+       }
+       return bref;
+}
index c78a28a..6170613 100644 (file)
@@ -5,7 +5,7 @@ includedir=@includedir@
 
 Name: libdrm_nouveau
 Description: Userspace interface to nouveau kernel DRM services
-Version: 0.6
+Version: 2.4.33
 Libs: -L${libdir} -ldrm_nouveau
 Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/nouveau
 Requires.private: libdrm
diff --git a/nouveau/nouveau.c b/nouveau/nouveau.c
new file mode 100644 (file)
index 0000000..5aa4107
--- /dev/null
@@ -0,0 +1,492 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdbool.h>
+#include <assert.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+#include "libdrm_lists.h"
+#include "nouveau_drm.h"
+
+#include "nouveau.h"
+#include "private.h"
+
+#ifdef DEBUG
+uint32_t nouveau_debug = 0;
+
+static void
+debug_init(char *args)
+{
+       if (args) {
+               int n = strtol(args, NULL, 0);
+               if (n >= 0)
+                       nouveau_debug = n;
+       }
+}
+#endif
+
+/* this is the old libdrm's version of nouveau_device_wrap(), the symbol
+ * is kept here to prevent AIGLX from crashing if the DDX is linked against
+ * the new libdrm, but the DRI driver against the old
+ */
+int
+nouveau_device_open_existing(struct nouveau_device **pdev, int close, int fd,
+                            drm_context_t ctx)
+{
+       return -EACCES;
+}
+
+int
+nouveau_device_wrap(int fd, int close, struct nouveau_device **pdev)
+{
+       struct nouveau_device_priv *nvdev = calloc(1, sizeof(*nvdev));
+       struct nouveau_device *dev = &nvdev->base;
+       uint64_t chipset, vram, gart, bousage;
+       drmVersionPtr ver;
+       int ret;
+
+#ifdef DEBUG
+       debug_init(getenv("NOUVEAU_LIBDRM_DEBUG"));
+#endif
+
+       if (!nvdev)
+               return -ENOMEM;
+       nvdev->base.fd = fd;
+
+       ver = drmGetVersion(fd);
+       if (ver) dev->drm_version = (ver->version_major << 24) |
+                                   (ver->version_minor << 8) |
+                                    ver->version_patchlevel;
+       drmFreeVersion(ver);
+
+       if ( dev->drm_version != 0x00000010 &&
+           (dev->drm_version <  0x01000000 ||
+            dev->drm_version >= 0x02000000)) {
+               nouveau_device_del(&dev);
+               return -EINVAL;
+       }
+
+       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_CHIPSET_ID, &chipset);
+       if (ret == 0)
+       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_FB_SIZE, &vram);
+       if (ret == 0)
+       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_AGP_SIZE, &gart);
+       if (ret) {
+               nouveau_device_del(&dev);
+               return ret;
+       }
+
+       ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_HAS_BO_USAGE, &bousage);
+       if (ret == 0)
+               nvdev->have_bo_usage = (bousage != 0);
+
+       nvdev->close = close;
+       DRMINITLISTHEAD(&nvdev->bo_list);
+       nvdev->base.object.oclass = NOUVEAU_DEVICE_CLASS;
+       nvdev->base.lib_version = 0x01000000;
+       nvdev->base.chipset = chipset;
+       nvdev->base.vram_size = vram;
+       nvdev->base.gart_size = gart;
+       nvdev->base.vram_limit = (nvdev->base.vram_size * 80) / 100;
+       nvdev->base.gart_limit = (nvdev->base.gart_size * 80) / 100;
+
+       *pdev = &nvdev->base;
+       return 0;
+}
+
+int
+nouveau_device_open(const char *busid, struct nouveau_device **pdev)
+{
+       int ret = -ENODEV, fd = drmOpen("nouveau", busid);
+       if (fd >= 0) {
+               ret = nouveau_device_wrap(fd, 1, pdev);
+               if (ret)
+                       drmClose(fd);
+       }
+       return ret;
+}
+
+void
+nouveau_device_del(struct nouveau_device **pdev)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(*pdev);
+       if (nvdev) {
+               if (nvdev->close)
+                       drmClose(nvdev->base.fd);
+               free(nvdev->client);
+               free(nvdev);
+               *pdev = NULL;
+       }
+}
+
+int
+nouveau_getparam(struct nouveau_device *dev, uint64_t param, uint64_t *value)
+{
+       struct drm_nouveau_getparam r = { param, 0 };
+       int fd = dev->fd, ret =
+               drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &r, sizeof(r));
+       *value = r.value;
+       return ret;
+}
+
+int
+nouveau_setparam(struct nouveau_device *dev, uint64_t param, uint64_t value)
+{
+       struct drm_nouveau_setparam r = { param, value };
+       return drmCommandWrite(dev->fd, DRM_NOUVEAU_SETPARAM, &r, sizeof(r));
+}
+
+int
+nouveau_client_new(struct nouveau_device *dev, struct nouveau_client **pclient)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct nouveau_client_priv *pcli;
+       int id = 0, i, ret = -ENOMEM;
+       uint32_t *clients;
+
+       for (i = 0; i < nvdev->nr_client; i++) {
+               id = ffs(nvdev->client[i]) - 1;
+               if (id >= 0)
+                       goto out;
+       }
+
+       clients = realloc(nvdev->client, sizeof(uint32_t) * (i + 1));
+       if (!clients)
+               return ret;
+       nvdev->client = clients;
+       nvdev->client[i] = 0;
+       nvdev->nr_client++;
+
+out:
+       pcli = calloc(1, sizeof(*pcli));
+       if (pcli) {
+               nvdev->client[i] |= (1 << id);
+               pcli->base.device = dev;
+               pcli->base.id = (i * 32) + id;
+               ret = 0;
+       }
+
+       *pclient = &pcli->base;
+       return ret;
+}
+
+void
+nouveau_client_del(struct nouveau_client **pclient)
+{
+       struct nouveau_client_priv *pcli = nouveau_client(*pclient);
+       struct nouveau_device_priv *nvdev;
+       if (pcli) {
+               int id = pcli->base.id;
+               nvdev = nouveau_device(pcli->base.device);
+               nvdev->client[id / 32] &= ~(1 << (id % 32));
+               free(pcli->kref);
+               free(pcli);
+       }
+}
+
+int
+nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
+                  uint32_t oclass, void *data, uint32_t length,
+                  struct nouveau_object **pobj)
+{
+       struct nouveau_device *dev;
+       struct nouveau_object *obj;
+       int ret = -EINVAL;
+
+       if (length == 0)
+               length = sizeof(struct nouveau_object *);
+       obj = malloc(sizeof(*obj) + length);
+       obj->parent = parent;
+       obj->handle = handle;
+       obj->oclass = oclass;
+       obj->length = length;
+       obj->data = obj + 1;
+       if (data)
+               memcpy(obj->data, data, length);
+       *(struct nouveau_object **)obj->data = obj;
+
+       dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+       switch (parent->oclass) {
+       case NOUVEAU_DEVICE_CLASS:
+               switch (obj->oclass) {
+               case NOUVEAU_FIFO_CHANNEL_CLASS:
+               {
+                       if (dev->chipset < 0xc0)
+                               ret = abi16_chan_nv04(obj);
+                       else
+                               ret = abi16_chan_nvc0(obj);
+               }
+                       break;
+               default:
+                       break;
+               }
+               break;
+       case NOUVEAU_FIFO_CHANNEL_CLASS:
+               switch (obj->oclass) {
+               case NOUVEAU_NOTIFIER_CLASS:
+                       ret = abi16_ntfy(obj);
+                       break;
+               default:
+                       ret = abi16_engobj(obj);
+                       break;
+               }
+       default:
+               break;
+       }
+
+       if (ret) {
+               free(obj);
+               return ret;
+       }
+
+       *pobj = obj;
+       return 0;
+}
+
+void
+nouveau_object_del(struct nouveau_object **pobj)
+{
+       struct nouveau_object *obj = *pobj;
+       struct nouveau_device *dev;
+       if (obj) {
+               dev = nouveau_object_find(obj, NOUVEAU_DEVICE_CLASS);
+               if (obj->oclass == NOUVEAU_FIFO_CHANNEL_CLASS) {
+                       struct drm_nouveau_channel_free req;
+                       req.channel = obj->handle;
+                       drmCommandWrite(dev->fd, DRM_NOUVEAU_CHANNEL_FREE,
+                                       &req, sizeof(req));
+               } else {
+                       struct drm_nouveau_gpuobj_free req;
+                       req.channel = obj->parent->handle;
+                       req.handle  = obj->handle;
+                       drmCommandWrite(dev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
+                                       &req, sizeof(req));
+               }
+       }
+       free(obj);
+       *pobj = NULL;
+}
+
+void *
+nouveau_object_find(struct nouveau_object *obj, uint32_t pclass)
+{
+       while (obj && obj->oclass != pclass) {
+               obj = obj->parent;
+               if (pclass == NOUVEAU_PARENT_CLASS)
+                       break;
+       }
+       return obj;
+}
+
+static void
+nouveau_bo_del(struct nouveau_bo *bo)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       struct drm_gem_close req = { bo->handle };
+       DRMLISTDEL(&nvbo->head);
+       if (bo->map)
+               munmap(bo->map, bo->size);
+       drmIoctl(bo->device->fd, DRM_IOCTL_GEM_CLOSE, &req);
+       free(nvbo);
+}
+
+int
+nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, uint32_t align,
+              uint64_t size, union nouveau_bo_config *config,
+              struct nouveau_bo **pbo)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct nouveau_bo_priv *nvbo = calloc(1, sizeof(*nvbo));
+       struct nouveau_bo *bo = &nvbo->base;
+       int ret;
+
+       if (!nvbo)
+               return -ENOMEM;
+       atomic_set(&nvbo->refcnt, 1);
+       bo->device = dev;
+       bo->flags = flags;
+       bo->size = size;
+
+       ret = abi16_bo_init(bo, align, config);
+       if (ret) {
+               free(nvbo);
+               return ret;
+       }
+
+       DRMLISTADD(&nvbo->head, &nvdev->bo_list);
+
+       *pbo = bo;
+       return 0;
+}
+
+int
+nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
+               struct nouveau_bo **pbo)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct drm_nouveau_gem_info req = { .handle = handle };
+       struct nouveau_bo_priv *nvbo;
+       int ret;
+
+       DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
+               if (nvbo->base.handle == handle) {
+                       *pbo = NULL;
+                       nouveau_bo_ref(&nvbo->base, pbo);
+                       return 0;
+               }
+       }
+
+       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_INFO,
+                                 &req, sizeof(req));
+       if (ret)
+               return ret;
+
+       nvbo = calloc(1, sizeof(*nvbo));
+       if (nvbo) {
+               atomic_set(&nvbo->refcnt, 1);
+               nvbo->base.device = dev;
+               abi16_bo_info(&nvbo->base, &req);
+               DRMLISTADD(&nvbo->head, &nvdev->bo_list);
+               *pbo = &nvbo->base;
+               return 0;
+       }
+
+       return -ENOMEM;
+}
+
+int
+nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
+                   struct nouveau_bo **pbo)
+{
+       struct nouveau_device_priv *nvdev = nouveau_device(dev);
+       struct nouveau_bo_priv *nvbo;
+       struct drm_gem_open req = { .name = name };
+       int ret;
+
+       DRMLISTFOREACHENTRY(nvbo, &nvdev->bo_list, head) {
+               if (nvbo->name == name) {
+                       *pbo = NULL;
+                       nouveau_bo_ref(&nvbo->base, pbo);
+                       return 0;
+               }
+       }
+
+       ret = drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req);
+       if (ret == 0) {
+               ret = nouveau_bo_wrap(dev, req.handle, pbo);
+               nouveau_bo((*pbo))->name = name;
+       }
+
+       return ret;
+}
+
+int
+nouveau_bo_name_get(struct nouveau_bo *bo, uint32_t *name)
+{
+       struct drm_gem_flink req = { .handle = bo->handle };
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       if (!nvbo->name) {
+               int ret = drmIoctl(bo->device->fd, DRM_IOCTL_GEM_FLINK, &req);
+               if (ret)
+                       return ret;
+               nvbo->name = req.name;
+       }
+       *name = nvbo->name;
+       return 0;
+}
+
+void
+nouveau_bo_ref(struct nouveau_bo *bo, struct nouveau_bo **pref)
+{
+       struct nouveau_bo *ref = *pref;
+       if (bo) {
+               atomic_inc(&nouveau_bo(bo)->refcnt);
+       }
+       if (ref) {
+               if (atomic_dec_and_test(&nouveau_bo(ref)->refcnt))
+                       nouveau_bo_del(ref);
+       }
+       *pref = bo;
+}
+
+int
+nouveau_bo_wait(struct nouveau_bo *bo, uint32_t access,
+               struct nouveau_client *client)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       struct drm_nouveau_gem_cpu_prep req;
+       struct nouveau_pushbuf *push;
+       int ret = 0;
+
+       if (!(access & NOUVEAU_BO_RDWR))
+               return 0;
+
+       push = cli_push_get(client, bo);
+       if (push && push->channel)
+               nouveau_pushbuf_kick(push, push->channel);
+
+       if (!nvbo->name && !(nvbo->access & NOUVEAU_BO_WR) &&
+                          !(      access & NOUVEAU_BO_WR))
+               return 0;
+
+       req.handle = bo->handle;
+       req.flags = 0;
+       if (access & NOUVEAU_BO_WR)
+               req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
+       if (access & NOUVEAU_BO_NOBLOCK)
+               req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
+
+       ret = drmCommandWrite(bo->device->fd, DRM_NOUVEAU_GEM_CPU_PREP,
+                             &req, sizeof(req));
+       if (ret == 0)
+               nvbo->access = 0;
+       return ret;
+}
+
+int
+nouveau_bo_map(struct nouveau_bo *bo, uint32_t access,
+              struct nouveau_client *client)
+{
+       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
+       if (bo->map == NULL) {
+               bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
+                              MAP_SHARED, bo->device->fd, nvbo->map_handle);
+               if (bo->map == MAP_FAILED) {
+                       bo->map = NULL;
+                       return -errno;
+               }
+       }
+       return nouveau_bo_wait(bo, access, client);
+}
diff --git a/nouveau/nouveau.h b/nouveau/nouveau.h
new file mode 100644 (file)
index 0000000..51a9598
--- /dev/null
@@ -0,0 +1,212 @@
+#ifndef __NOUVEAU_H__
+#define __NOUVEAU_H__
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#define NOUVEAU_DEVICE_CLASS       0x80000000
+#define NOUVEAU_FIFO_CHANNEL_CLASS 0x80000001
+#define NOUVEAU_NOTIFIER_CLASS     0x80000002
+#define NOUVEAU_PARENT_CLASS       0xffffffff
+
+struct nouveau_list {
+       struct nouveau_list *prev;
+       struct nouveau_list *next;
+};
+
+struct nouveau_object {
+       struct nouveau_object *parent;
+       uint64_t handle;
+       uint32_t oclass;
+       uint32_t length;
+       void *data;
+};
+
+struct nouveau_fifo {
+       struct nouveau_object *object;
+       uint32_t channel;
+       uint32_t pushbuf;
+       uint64_t unused1[3];
+};
+
+struct nv04_fifo {
+       struct nouveau_fifo base;
+       uint32_t vram;
+       uint32_t gart;
+       uint32_t notify;
+};
+
+struct nvc0_fifo {
+       struct nouveau_fifo base;
+       uint32_t notify;
+};
+
+struct nv04_notify {
+       struct nouveau_object *object;
+       uint32_t offset;
+       uint32_t length;
+};
+
+int  nouveau_object_new(struct nouveau_object *parent, uint64_t handle,
+                       uint32_t oclass, void *data, uint32_t length,
+                       struct nouveau_object **);
+void nouveau_object_del(struct nouveau_object **);
+void *nouveau_object_find(struct nouveau_object *, uint32_t parent_class);
+
+struct nouveau_device {
+       struct nouveau_object object;
+       int fd;
+       uint32_t lib_version;
+       uint32_t drm_version;
+       uint32_t chipset;
+       uint64_t vram_size;
+       uint64_t gart_size;
+       uint64_t vram_limit;
+       uint64_t gart_limit;
+};
+
+int  nouveau_device_wrap(int fd, int close, struct nouveau_device **);
+int  nouveau_device_open(const char *busid, struct nouveau_device **);
+void nouveau_device_del(struct nouveau_device **);
+int  nouveau_getparam(struct nouveau_device *, uint64_t param, uint64_t *value);
+int  nouveau_setparam(struct nouveau_device *, uint64_t param, uint64_t value);
+
+struct nouveau_client {
+       struct nouveau_device *device;
+       int id;
+};
+
+int  nouveau_client_new(struct nouveau_device *, struct nouveau_client **);
+void nouveau_client_del(struct nouveau_client **);
+
+union nouveau_bo_config {
+       struct {
+#define NV04_BO_16BPP 0x00000001
+#define NV04_BO_32BPP 0x00000002
+#define NV04_BO_ZETA  0x00000004
+               uint32_t surf_flags;
+               uint32_t surf_pitch;
+       } nv04;
+       struct {
+               uint32_t memtype;
+               uint32_t tile_mode;
+       } nv50;
+       struct {
+               uint32_t memtype;
+               uint32_t tile_mode;
+       } nvc0;
+       uint32_t data[8];
+};
+
+#define NOUVEAU_BO_VRAM    0x00000001
+#define NOUVEAU_BO_GART    0x00000002
+#define NOUVEAU_BO_APER   (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)
+#define NOUVEAU_BO_RD      0x00000100
+#define NOUVEAU_BO_WR      0x00000200
+#define NOUVEAU_BO_RDWR   (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
+#define NOUVEAU_BO_NOBLOCK 0x00000400
+#define NOUVEAU_BO_LOW     0x00001000
+#define NOUVEAU_BO_HIGH    0x00002000
+#define NOUVEAU_BO_OR      0x00004000
+#define NOUVEAU_BO_MAP     0x80000000
+#define NOUVEAU_BO_CONTIG  0x40000000
+#define NOUVEAU_BO_NOSNOOP 0x20000000
+
+struct nouveau_bo {
+       struct nouveau_device *device;
+       uint32_t handle;
+       uint64_t size;
+       uint32_t flags;
+       uint64_t offset;
+       void *map;
+       union nouveau_bo_config config;
+};
+
+int  nouveau_bo_new(struct nouveau_device *, uint32_t flags, uint32_t align,
+                   uint64_t size, union nouveau_bo_config *,
+                   struct nouveau_bo **);
+int  nouveau_bo_wrap(struct nouveau_device *, uint32_t handle,
+                    struct nouveau_bo **);
+int  nouveau_bo_name_ref(struct nouveau_device *dev, uint32_t name,
+                        struct nouveau_bo **);
+int  nouveau_bo_name_get(struct nouveau_bo *, uint32_t *name);
+void nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
+int  nouveau_bo_map(struct nouveau_bo *, uint32_t access,
+                   struct nouveau_client *);
+int  nouveau_bo_wait(struct nouveau_bo *, uint32_t access,
+                    struct nouveau_client *);
+
+struct nouveau_bufref {
+       struct nouveau_list thead;
+       struct nouveau_bo *bo;
+       uint32_t packet;
+       uint32_t flags;
+       uint32_t data;
+       uint32_t vor;
+       uint32_t tor;
+       uint32_t priv_data;
+       void *priv;
+};
+
+struct nouveau_bufctx {
+       struct nouveau_client *client;
+       struct nouveau_list head;
+       struct nouveau_list pending;
+       struct nouveau_list current;
+       int relocs;
+};
+
+int  nouveau_bufctx_new(struct nouveau_client *, int bins,
+                       struct nouveau_bufctx **);
+void nouveau_bufctx_del(struct nouveau_bufctx **);
+struct nouveau_bufref *
+nouveau_bufctx_refn(struct nouveau_bufctx *, int bin,
+                   struct nouveau_bo *, uint32_t flags);
+struct nouveau_bufref *
+nouveau_bufctx_mthd(struct nouveau_bufctx *, int bin,  uint32_t packet,
+                   struct nouveau_bo *, uint64_t data, uint32_t flags,
+                   uint32_t vor, uint32_t tor);
+void nouveau_bufctx_reset(struct nouveau_bufctx *, int bin);
+
+struct nouveau_pushbuf_krec;
+struct nouveau_pushbuf {
+       struct nouveau_client *client;
+       struct nouveau_object *channel;
+       struct nouveau_bufctx *bufctx;
+       void (*kick_notify)(struct nouveau_pushbuf *);
+       void *user_priv;
+       uint32_t rsvd_kick;
+       uint32_t flags;
+       uint32_t *cur;
+       uint32_t *end;
+};
+
+struct nouveau_pushbuf_refn {
+       struct nouveau_bo *bo;
+       uint32_t flags;
+};
+
+int  nouveau_pushbuf_new(struct nouveau_client *, struct nouveau_object *channel,
+                        int nr, uint32_t size, bool immediate,
+                        struct nouveau_pushbuf **);
+void nouveau_pushbuf_del(struct nouveau_pushbuf **);
+int  nouveau_pushbuf_space(struct nouveau_pushbuf *, uint32_t dwords,
+                          uint32_t relocs, uint32_t pushes);
+void nouveau_pushbuf_data(struct nouveau_pushbuf *, struct nouveau_bo *,
+                         uint64_t offset, uint64_t length);
+int  nouveau_pushbuf_refn(struct nouveau_pushbuf *,
+                         struct nouveau_pushbuf_refn *, int nr);
+/* Emits a reloc into the push buffer at the current position, you *must*
+ * have previously added the referenced buffer to a buffer context, and
+ * validated it against the current push buffer.
+ */
+void nouveau_pushbuf_reloc(struct nouveau_pushbuf *, struct nouveau_bo *,
+                          uint32_t data, uint32_t flags,
+                          uint32_t vor, uint32_t tor);
+int  nouveau_pushbuf_validate(struct nouveau_pushbuf *);
+uint32_t nouveau_pushbuf_refd(struct nouveau_pushbuf *, struct nouveau_bo *);
+int  nouveau_pushbuf_kick(struct nouveau_pushbuf *, struct nouveau_object *channel);
+struct nouveau_bufctx *
+nouveau_pushbuf_bufctx(struct nouveau_pushbuf *, struct nouveau_bufctx *);
+
+#endif
diff --git a/nouveau/nouveau_bo.c b/nouveau/nouveau_bo.c
deleted file mode 100644 (file)
index d6bb22d..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include <stdint.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-
-#include <sys/mman.h>
-
-#include "nouveau_private.h"
-
-int
-nouveau_bo_init(struct nouveau_device *dev)
-{
-       return 0;
-}
-
-void
-nouveau_bo_takedown(struct nouveau_device *dev)
-{
-}
-
-static int
-nouveau_bo_info(struct nouveau_bo_priv *nvbo, struct drm_nouveau_gem_info *arg)
-{
-       nvbo->handle = nvbo->base.handle = arg->handle;
-       nvbo->domain = arg->domain;
-       nvbo->size = arg->size;
-       nvbo->offset = arg->offset;
-       nvbo->map_handle = arg->map_handle;
-       nvbo->base.tile_mode = arg->tile_mode;
-       /* XXX - flag inverted for backwards compatibility */
-       nvbo->base.tile_flags = arg->tile_flags ^ NOUVEAU_GEM_TILE_NONCONTIG;
-       return 0;
-}
-
-static int
-nouveau_bo_allocated(struct nouveau_bo_priv *nvbo)
-{
-       if (nvbo->sysmem || nvbo->handle)
-               return 1;
-       return 0;
-}
-
-static int
-nouveau_bo_ualloc(struct nouveau_bo_priv *nvbo)
-{
-       if (nvbo->user || nvbo->sysmem) {
-               assert(nvbo->sysmem);
-               return 0;
-       }
-
-       nvbo->sysmem = malloc(nvbo->size);
-       if (!nvbo->sysmem)
-               return -ENOMEM;
-
-       return 0;
-}
-
-static void
-nouveau_bo_ufree(struct nouveau_bo_priv *nvbo)
-{
-       if (nvbo->sysmem) {
-               if (!nvbo->user)
-                       free(nvbo->sysmem);
-               nvbo->sysmem = NULL;
-       }
-}
-
-static void
-nouveau_bo_kfree(struct nouveau_bo_priv *nvbo)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
-       struct drm_gem_close req;
-
-       if (!nvbo->handle)
-               return;
-
-       if (nvbo->map) {
-               munmap(nvbo->map, nvbo->size);
-               nvbo->map = NULL;
-       }
-
-       req.handle = nvbo->handle;
-       nvbo->handle = 0;
-       drmIoctl(nvdev->fd, DRM_IOCTL_GEM_CLOSE, &req);
-}
-
-static int
-nouveau_bo_kalloc(struct nouveau_bo_priv *nvbo, struct nouveau_channel *chan)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
-       struct drm_nouveau_gem_new req;
-       struct drm_nouveau_gem_info *info = &req.info;
-       int ret;
-
-       if (nvbo->handle)
-               return 0;
-
-       req.channel_hint = chan ? chan->id : 0;
-       req.align = nvbo->align;
-
-
-       info->size = nvbo->size;
-       info->domain = 0;
-
-       if (nvbo->flags & NOUVEAU_BO_VRAM)
-               info->domain |= NOUVEAU_GEM_DOMAIN_VRAM;
-       if (nvbo->flags & NOUVEAU_BO_GART)
-               info->domain |= NOUVEAU_GEM_DOMAIN_GART;
-       if (!info->domain) {
-               info->domain |= (NOUVEAU_GEM_DOMAIN_VRAM |
-                                NOUVEAU_GEM_DOMAIN_GART);
-       }
-
-       if (nvbo->flags & NOUVEAU_BO_MAP)
-               info->domain |= NOUVEAU_GEM_DOMAIN_MAPPABLE;
-
-       info->tile_mode = nvbo->base.tile_mode;
-       info->tile_flags = nvbo->base.tile_flags;
-       /* XXX - flag inverted for backwards compatibility */
-       info->tile_flags ^= NOUVEAU_GEM_TILE_NONCONTIG;
-       if (!nvdev->has_bo_usage)
-               info->tile_flags &= NOUVEAU_GEM_TILE_LAYOUT_MASK;
-
-       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_NEW,
-                                 &req, sizeof(req));
-       if (ret)
-               return ret;
-
-       nouveau_bo_info(nvbo, &req.info);
-       return 0;
-}
-
-static int
-nouveau_bo_kmap(struct nouveau_bo_priv *nvbo)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(nvbo->base.device);
-
-       if (nvbo->map)
-               return 0;
-
-       if (!nvbo->map_handle)
-               return -EINVAL;
-
-       nvbo->map = mmap(0, nvbo->size, PROT_READ | PROT_WRITE,
-                        MAP_SHARED, nvdev->fd, nvbo->map_handle);
-       if (nvbo->map == MAP_FAILED) {
-               nvbo->map = NULL;
-               return -errno;
-       }
-
-       return 0;
-}
-
-int
-nouveau_bo_new_tile(struct nouveau_device *dev, uint32_t flags, int align,
-                   int size, uint32_t tile_mode, uint32_t tile_flags,
-                   struct nouveau_bo **bo)
-{
-       struct nouveau_bo_priv *nvbo;
-       int ret;
-
-       if (!dev || !bo || *bo)
-               return -EINVAL;
-
-       nvbo = calloc(1, sizeof(struct nouveau_bo_priv));
-       if (!nvbo)
-               return -ENOMEM;
-       nvbo->base.device = dev;
-       nvbo->base.size = size;
-       nvbo->base.tile_mode = tile_mode;
-       nvbo->base.tile_flags = tile_flags;
-
-       nvbo->refcount = 1;
-       nvbo->flags = flags;
-       nvbo->size = size;
-       nvbo->align = align;
-
-       if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
-               ret = nouveau_bo_kalloc(nvbo, NULL);
-               if (ret) {
-                       nouveau_bo_ref(NULL, (void *)&nvbo);
-                       return ret;
-               }
-       }
-
-       *bo = &nvbo->base;
-       return 0;
-}
-
-int
-nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align,
-              int size, struct nouveau_bo **bo)
-{
-       return nouveau_bo_new_tile(dev, flags, align, size, 0, 0, bo);
-}
-
-int
-nouveau_bo_user(struct nouveau_device *dev, void *ptr, int size,
-               struct nouveau_bo **bo)
-{
-       struct nouveau_bo_priv *nvbo;
-       int ret;
-
-       ret = nouveau_bo_new(dev, NOUVEAU_BO_MAP, 0, size, bo);
-       if (ret)
-               return ret;
-       nvbo = nouveau_bo(*bo);
-
-       nvbo->sysmem = ptr;
-       nvbo->user = 1;
-       return 0;
-}
-
-int
-nouveau_bo_wrap(struct nouveau_device *dev, uint32_t handle,
-               struct nouveau_bo **bo)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(dev);
-       struct drm_nouveau_gem_info req;
-       struct nouveau_bo_priv *nvbo;
-       int ret;
-
-       ret = nouveau_bo_new(dev, 0, 0, 0, bo);
-       if (ret)
-               return ret;
-       nvbo = nouveau_bo(*bo);
-
-       req.handle = handle;
-       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_INFO,
-                                 &req, sizeof(req));
-       if (ret) {
-               nouveau_bo_ref(NULL, bo);
-               return ret;
-       }
-
-       nouveau_bo_info(nvbo, &req);
-       nvbo->base.size = nvbo->size;
-       return 0;
-}
-
-int
-nouveau_bo_handle_get(struct nouveau_bo *bo, uint32_t *handle)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-       int ret;
-       if (!bo || !handle)
-               return -EINVAL;
-
-       if (!nvbo->global_handle) {
-               struct drm_gem_flink req;
-               ret = nouveau_bo_kalloc(nvbo, NULL);
-               if (ret)
-                       return ret;
-
-               req.handle = nvbo->handle;
-               ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_FLINK, &req);
-               if (ret) {
-                       nouveau_bo_kfree(nvbo);
-                       return ret;
-               }
-
-               nvbo->global_handle = req.name;
-       }
-       *handle = nvbo->global_handle;
-       return 0;
-}
-int
-nouveau_bo_handle_ref(struct nouveau_device *dev, uint32_t handle,
-                     struct nouveau_bo **bo)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(dev);
-       struct nouveau_bo_priv *nvbo;
-       struct drm_gem_open req;
-       int ret;
-
-       req.name = handle;
-       ret = drmIoctl(nvdev->fd, DRM_IOCTL_GEM_OPEN, &req);
-       if (ret) {
-               nouveau_bo_ref(NULL, bo);
-               return ret;
-       }
-
-       ret = nouveau_bo_wrap(dev, req.handle, bo);
-       if (ret) {
-               nouveau_bo_ref(NULL, bo);
-               return ret;
-       }
-
-       nvbo = nouveau_bo(*bo);
-       nvbo->base.handle = nvbo->handle;
-       return 0;
-} 
-
-static void
-nouveau_bo_del(struct nouveau_bo **bo)
-{
-       struct nouveau_bo_priv *nvbo;
-
-       if (!bo || !*bo)
-               return;
-       nvbo = nouveau_bo(*bo);
-       *bo = NULL;
-
-       if (--nvbo->refcount)
-               return;
-
-       if (nvbo->pending) {
-               nvbo->pending = NULL;
-               nouveau_pushbuf_flush(nvbo->pending_channel, 0);
-       }
-
-       nouveau_bo_ufree(nvbo);
-       nouveau_bo_kfree(nvbo);
-       free(nvbo);
-}
-
-int
-nouveau_bo_ref(struct nouveau_bo *ref, struct nouveau_bo **pbo)
-{
-       if (!pbo)
-               return -EINVAL;
-
-       if (ref)
-               nouveau_bo(ref)->refcount++;
-
-       if (*pbo)
-               nouveau_bo_del(pbo);
-
-       *pbo = ref;
-       return 0;
-}
-
-static int
-nouveau_bo_wait(struct nouveau_bo *bo, int cpu_write, int no_wait, int no_block)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-       struct drm_nouveau_gem_cpu_prep req;
-       int ret;
-
-       if (!nvbo->global_handle && !nvbo->write_marker && !cpu_write)
-               return 0;
-
-       if (nvbo->pending &&
-           (nvbo->pending->write_domains || cpu_write)) {
-               nvbo->pending = NULL;
-               nouveau_pushbuf_flush(nvbo->pending_channel, 0);
-       }
-
-       req.handle = nvbo->handle;
-       req.flags = 0;
-       if (cpu_write)
-               req.flags |= NOUVEAU_GEM_CPU_PREP_WRITE;
-       if (no_wait)
-               req.flags |= NOUVEAU_GEM_CPU_PREP_NOWAIT;
-       if (no_block)
-               req.flags |= NOUVEAU_GEM_CPU_PREP_NOBLOCK;
-
-       do {
-               ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_PREP,
-                                     &req, sizeof(req));
-       } while (ret == -EAGAIN);
-       if (ret)
-               return ret;
-
-       if (ret == 0)
-               nvbo->write_marker = 0;
-       return 0;
-}
-
-int
-nouveau_bo_map_range(struct nouveau_bo *bo, uint32_t delta, uint32_t size,
-                    uint32_t flags)
-{
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-       int ret;
-
-       if (!nvbo || bo->map)
-               return -EINVAL;
-
-       if (!nouveau_bo_allocated(nvbo)) {
-               if (nvbo->flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
-                       ret = nouveau_bo_kalloc(nvbo, NULL);
-                       if (ret)
-                               return ret;
-               }
-
-               if (!nouveau_bo_allocated(nvbo)) {
-                       ret = nouveau_bo_ualloc(nvbo);
-                       if (ret)
-                               return ret;
-               }
-       }
-
-       if (nvbo->sysmem) {
-               bo->map = (char *)nvbo->sysmem + delta;
-       } else {
-               ret = nouveau_bo_kmap(nvbo);
-               if (ret)
-                       return ret;
-
-               if (!(flags & NOUVEAU_BO_NOSYNC)) {
-                       ret = nouveau_bo_wait(bo, (flags & NOUVEAU_BO_WR),
-                                             (flags & NOUVEAU_BO_NOWAIT), 0);
-                       if (ret)
-                               return ret;
-
-                       nvbo->map_refcnt++;
-               }
-
-               bo->map = (char *)nvbo->map + delta;
-       }
-
-       return 0;
-}
-
-void
-nouveau_bo_map_flush(struct nouveau_bo *bo, uint32_t delta, uint32_t size)
-{
-}
-
-int
-nouveau_bo_map(struct nouveau_bo *bo, uint32_t flags)
-{
-       return nouveau_bo_map_range(bo, 0, bo->size, flags);
-}
-
-void
-nouveau_bo_unmap(struct nouveau_bo *bo)
-{
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-
-       if (bo->map && !nvbo->sysmem && nvbo->map_refcnt) {
-               struct nouveau_device_priv *nvdev = nouveau_device(bo->device);
-               struct drm_nouveau_gem_cpu_fini req;
-
-               req.handle = nvbo->handle;
-               drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GEM_CPU_FINI,
-                               &req, sizeof(req));
-               nvbo->map_refcnt--;
-       }
-
-       bo->map = NULL;
-}
-
-int
-nouveau_bo_busy(struct nouveau_bo *bo, uint32_t access)
-{
-       return nouveau_bo_wait(bo, (access & NOUVEAU_BO_WR), 1, 1);
-}
-
-uint32_t
-nouveau_bo_pending(struct nouveau_bo *bo)
-{
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-       uint32_t flags;
-
-       if (!nvbo->pending)
-               return 0;
-
-       flags = 0;
-       if (nvbo->pending->read_domains)
-               flags |= NOUVEAU_BO_RD;
-       if (nvbo->pending->write_domains)
-               flags |= NOUVEAU_BO_WR;
-
-       return flags;
-}
-
-struct drm_nouveau_gem_pushbuf_bo *
-nouveau_bo_emit_buffer(struct nouveau_channel *chan, struct nouveau_bo *bo)
-{
-       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-       struct drm_nouveau_gem_pushbuf_bo *pbbo;
-       struct nouveau_bo *ref = NULL;
-       int ret;
-
-       if (nvbo->pending)
-               return nvbo->pending;
-
-       if (!nvbo->handle) {
-               ret = nouveau_bo_kalloc(nvbo, chan);
-               if (ret)
-                       return NULL;
-
-               if (nvbo->sysmem) {
-                       void *sysmem_tmp = nvbo->sysmem;
-
-                       nvbo->sysmem = NULL;
-                       ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
-                       if (ret)
-                               return NULL;
-                       nvbo->sysmem = sysmem_tmp;
-
-                       memcpy(bo->map, nvbo->sysmem, nvbo->base.size);
-                       nouveau_bo_ufree(nvbo);
-                       nouveau_bo_unmap(bo);
-               }
-       }
-
-       if (nvpb->nr_buffers >= NOUVEAU_GEM_MAX_BUFFERS)
-               return NULL;
-       pbbo = nvpb->buffers + nvpb->nr_buffers++;
-       nvbo->pending = pbbo;
-       nvbo->pending_channel = chan;
-       nvbo->pending_refcnt = 0;
-
-       nouveau_bo_ref(bo, &ref);
-       pbbo->user_priv = (uint64_t)(unsigned long)ref;
-       pbbo->handle = nvbo->handle;
-       pbbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM | NOUVEAU_GEM_DOMAIN_GART;
-       pbbo->read_domains = 0;
-       pbbo->write_domains = 0;
-       pbbo->presumed.domain = nvbo->domain;
-       pbbo->presumed.offset = nvbo->offset;
-       pbbo->presumed.valid = 1;
-       return pbbo;
-}
diff --git a/nouveau/nouveau_bo.h b/nouveau/nouveau_bo.h
deleted file mode 100644 (file)
index 3a1f2d4..0000000
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_BO_H__
-#define __NOUVEAU_BO_H__
-
-/* Relocation/Buffer type flags */
-#define NOUVEAU_BO_VRAM   (1 << 0)
-#define NOUVEAU_BO_GART   (1 << 1)
-#define NOUVEAU_BO_RD     (1 << 2)
-#define NOUVEAU_BO_WR     (1 << 3)
-#define NOUVEAU_BO_RDWR   (NOUVEAU_BO_RD | NOUVEAU_BO_WR)
-#define NOUVEAU_BO_MAP    (1 << 4)
-#define NOUVEAU_BO_LOW    (1 << 6)
-#define NOUVEAU_BO_HIGH   (1 << 7)
-#define NOUVEAU_BO_OR     (1 << 8)
-#define NOUVEAU_BO_INVAL  (1 << 12)
-#define NOUVEAU_BO_NOSYNC (1 << 13)
-#define NOUVEAU_BO_NOWAIT (1 << 14)
-#define NOUVEAU_BO_IFLUSH (1 << 15)
-#define NOUVEAU_BO_DUMMY  (1 << 31)
-
-#define NOUVEAU_BO_TILE_LAYOUT_MASK 0x0000ff00
-#define NOUVEAU_BO_TILE_16BPP       0x00000001
-#define NOUVEAU_BO_TILE_32BPP       0x00000002
-#define NOUVEAU_BO_TILE_ZETA        0x00000004
-#define NOUVEAU_BO_TILE_SCANOUT     0x00000008
-
-struct nouveau_bo {
-       struct nouveau_device *device;
-       uint32_t handle;
-
-       uint64_t size;
-       void *map;
-
-       uint32_t tile_mode;
-       uint32_t tile_flags;
-};
-
-int
-nouveau_bo_new(struct nouveau_device *, uint32_t flags, int align, int size,
-              struct nouveau_bo **);
-
-int
-nouveau_bo_new_tile(struct nouveau_device *, uint32_t flags, int align,
-                   int size, uint32_t tile_mode, uint32_t tile_flags,
-                   struct nouveau_bo **);
-
-int
-nouveau_bo_user(struct nouveau_device *, void *ptr, int size,
-               struct nouveau_bo **);
-
-int
-nouveau_bo_wrap(struct nouveau_device *, uint32_t handle, struct nouveau_bo **);
-
-int
-nouveau_bo_handle_get(struct nouveau_bo *, uint32_t *);
-
-int
-nouveau_bo_handle_ref(struct nouveau_device *, uint32_t handle,
-                     struct nouveau_bo **);
-
-int
-nouveau_bo_ref(struct nouveau_bo *, struct nouveau_bo **);
-
-int
-nouveau_bo_map_range(struct nouveau_bo *, uint32_t delta, uint32_t size,
-                    uint32_t flags);
-
-void
-nouveau_bo_map_flush(struct nouveau_bo *, uint32_t delta, uint32_t size);
-
-int
-nouveau_bo_map(struct nouveau_bo *, uint32_t flags);
-
-void
-nouveau_bo_unmap(struct nouveau_bo *);
-
-int
-nouveau_bo_busy(struct nouveau_bo *, uint32_t access);
-
-uint32_t
-nouveau_bo_pending(struct nouveau_bo *);
-
-#endif
diff --git a/nouveau/nouveau_channel.c b/nouveau/nouveau_channel.c
deleted file mode 100644 (file)
index 96fa03b..0000000
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include "nouveau_private.h"
-
-int
-nouveau_channel_alloc(struct nouveau_device *dev, uint32_t fb_ctxdma,
-                     uint32_t tt_ctxdma, int pushbuf_size,
-                     struct nouveau_channel **chan)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(dev);
-       struct nouveau_channel_priv *nvchan;
-       unsigned i;
-       int ret;
-
-       if (!nvdev || !chan || *chan)
-           return -EINVAL;
-
-       nvchan = calloc(1, sizeof(struct nouveau_channel_priv));
-       if (!nvchan)
-               return -ENOMEM;
-       nvchan->base.device = dev;
-
-       nvchan->drm.fb_ctxdma_handle = fb_ctxdma;
-       nvchan->drm.tt_ctxdma_handle = tt_ctxdma;
-       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_CHANNEL_ALLOC,
-                                 &nvchan->drm, sizeof(nvchan->drm));
-       if (ret) {
-               free(nvchan);
-               return ret;
-       }
-
-       nvchan->base.id = nvchan->drm.channel;
-       if (nouveau_grobj_ref(&nvchan->base, nvchan->drm.fb_ctxdma_handle,
-                             &nvchan->base.vram) ||
-           nouveau_grobj_ref(&nvchan->base, nvchan->drm.tt_ctxdma_handle,
-                             &nvchan->base.gart)) {
-               nouveau_channel_free((void *)&nvchan);
-               return -EINVAL;
-       }
-
-       /* Mark all DRM-assigned subchannels as in-use */
-       for (i = 0; i < nvchan->drm.nr_subchan; i++) {
-               struct nouveau_grobj_priv *gr = calloc(1, sizeof(*gr));
-
-               gr->base.bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
-               gr->base.subc = i;
-               gr->base.handle = nvchan->drm.subchan[i].handle;
-               gr->base.grclass = nvchan->drm.subchan[i].grclass;
-               gr->base.channel = &nvchan->base;
-
-               nvchan->base.subc[i].gr = &gr->base;
-       }
-
-       if (dev->chipset < 0xc0) {
-               ret = nouveau_bo_wrap(dev, nvchan->drm.notifier_handle,
-                                     &nvchan->notifier_bo);
-               if (!ret)
-                       ret = nouveau_bo_map(nvchan->notifier_bo,
-                                            NOUVEAU_BO_RDWR);
-               if (ret) {
-                       nouveau_channel_free((void *)&nvchan);
-                       return ret;
-               }
-
-               ret = nouveau_grobj_alloc(&nvchan->base, 0x00000000, 0x0030,
-                                         &nvchan->base.nullobj);
-               if (ret) {
-                       nouveau_channel_free((void *)&nvchan);
-                       return ret;
-               }
-       }
-
-       ret = nouveau_pushbuf_init(&nvchan->base, pushbuf_size);
-       if (ret) {
-               nouveau_channel_free((void *)&nvchan);
-               return ret;
-       }
-
-       *chan = &nvchan->base;
-       return 0;
-}
-
-void
-nouveau_channel_free(struct nouveau_channel **chan)
-{
-       struct nouveau_channel_priv *nvchan;
-       struct nouveau_device_priv *nvdev;
-       struct drm_nouveau_channel_free cf;
-       unsigned i;
-
-       if (!chan || !*chan)
-               return;
-       nvchan = nouveau_channel(*chan);
-       (*chan)->flush_notify = NULL;
-       *chan = NULL;
-       nvdev = nouveau_device(nvchan->base.device);
-
-       FIRE_RING(&nvchan->base);
-
-       nouveau_pushbuf_fini(&nvchan->base);
-       if (nvchan->notifier_bo) {
-               nouveau_bo_unmap(nvchan->notifier_bo);
-               nouveau_bo_ref(NULL, &nvchan->notifier_bo);
-       }
-
-       for (i = 0; i < nvchan->drm.nr_subchan; i++)
-               free(nvchan->base.subc[i].gr);
-
-       nouveau_grobj_free(&nvchan->base.vram);
-       nouveau_grobj_free(&nvchan->base.gart);
-       nouveau_grobj_free(&nvchan->base.nullobj);
-
-       cf.channel = nvchan->drm.channel;
-       drmCommandWrite(nvdev->fd, DRM_NOUVEAU_CHANNEL_FREE, &cf, sizeof(cf));
-       free(nvchan);
-}
-
-
diff --git a/nouveau/nouveau_channel.h b/nouveau/nouveau_channel.h
deleted file mode 100644 (file)
index d61a4c0..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_CHANNEL_H__
-#define __NOUVEAU_CHANNEL_H__
-
-struct nouveau_subchannel {
-       struct nouveau_grobj *gr;
-       unsigned sequence;
-};
-
-struct nouveau_channel {
-       uint32_t *cur;
-       uint32_t *end;
-
-       struct nouveau_device *device;
-       int id;
-
-       struct nouveau_grobj *nullobj;
-       struct nouveau_grobj *vram;
-       struct nouveau_grobj *gart;
-
-       void *user_private;
-       void (*hang_notify)(struct nouveau_channel *);
-       void (*flush_notify)(struct nouveau_channel *);
-
-       struct nouveau_subchannel subc[8];
-       unsigned subc_sequence;
-};
-
-int
-nouveau_channel_alloc(struct nouveau_device *, uint32_t fb, uint32_t tt,
-                     int pushbuf_size, struct nouveau_channel **);
-
-void
-nouveau_channel_free(struct nouveau_channel **);
-
-#endif
diff --git a/nouveau/nouveau_device.c b/nouveau/nouveau_device.c
deleted file mode 100644 (file)
index 425c5d2..0000000
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-
-#include "nouveau_private.h"
-
-int
-nouveau_device_open_existing(struct nouveau_device **dev, int close,
-                            int fd, drm_context_t ctx)
-{
-       struct nouveau_device_priv *nvdev;
-       drmVersionPtr ver;
-       uint64_t value;
-       int ret;
-
-       if (!dev || *dev)
-           return -EINVAL;
-
-       nvdev = calloc(1, sizeof(*nvdev));
-       if (!nvdev)
-           return -ENOMEM;
-       nvdev->fd = fd;
-       nvdev->ctx = ctx;
-       nvdev->needs_close = close;
-
-       ver = drmGetVersion(fd);
-       if (!ver) {
-               nouveau_device_close((void *)&nvdev);
-               return -EINVAL;
-       }
-
-       if ((ver->version_major == 0 && ver->version_patchlevel != 16) ||
-            ver->version_major > 1) {
-               nouveau_device_close((void *)&nvdev);
-               return -EINVAL;
-       }
-
-       drmFreeVersion(ver);
-
-       ret = nouveau_device_get_param(&nvdev->base,
-                                      NOUVEAU_GETPARAM_VM_VRAM_BASE, &value);
-       if (ret) {
-               nouveau_device_close((void *)&nvdev);
-               return ret;
-       }
-       nvdev->base.vm_vram_base = value;
-
-       ret = nouveau_device_get_param(&nvdev->base,
-                                      NOUVEAU_GETPARAM_FB_SIZE, &value);
-       if (ret) {
-               nouveau_device_close((void *)&nvdev);
-               return ret;
-       }
-       nvdev->base.vm_vram_size = value;
-
-       ret = nouveau_device_get_param(&nvdev->base,
-                                      NOUVEAU_GETPARAM_AGP_SIZE, &value);
-       if (ret) {
-               nouveau_device_close((void *)&nvdev);
-               return ret;
-       }
-       nvdev->base.vm_gart_size = value;
-
-       ret = nouveau_bo_init(&nvdev->base);
-       if (ret) {
-               nouveau_device_close((void *)&nvdev);
-               return ret;
-       }
-
-       ret = nouveau_device_get_param(&nvdev->base,
-                                      NOUVEAU_GETPARAM_CHIPSET_ID, &value);
-       if (ret) {
-               nouveau_device_close((void *)&nvdev);
-               return ret;
-       }
-       nvdev->base.chipset = value;
-
-       ret = nouveau_device_get_param(&nvdev->base,
-                                      NOUVEAU_GETPARAM_HAS_BO_USAGE, &value);
-       if (!ret)
-               nvdev->has_bo_usage = value;
-
-       *dev = &nvdev->base;
-       return 0;
-}
-
-int
-nouveau_device_open(struct nouveau_device **dev, const char *busid)
-{
-       drm_context_t ctx;
-       int fd, ret;
-
-       if (!dev || *dev)
-               return -EINVAL;
-
-       fd = drmOpen("nouveau", busid);
-       if (fd < 0)
-               return -EINVAL;
-
-       ret = drmCreateContext(fd, &ctx);
-       if (ret) {
-               drmClose(fd);
-               return ret;
-       }
-
-       ret = nouveau_device_open_existing(dev, 1, fd, ctx);
-       if (ret) {
-           drmDestroyContext(fd, ctx);
-           drmClose(fd);
-           return ret;
-       }
-
-       return 0;
-}
-
-void
-nouveau_device_close(struct nouveau_device **dev)
-{
-       struct nouveau_device_priv *nvdev;
-
-       if (!dev || !*dev)
-               return;
-       nvdev = nouveau_device(*dev);
-       *dev = NULL;
-
-       nouveau_bo_takedown(&nvdev->base);
-
-       if (nvdev->needs_close) {
-               drmDestroyContext(nvdev->fd, nvdev->ctx);
-               drmClose(nvdev->fd);
-       }
-       free(nvdev);
-}
-
-int
-nouveau_device_get_param(struct nouveau_device *dev,
-                        uint64_t param, uint64_t *value)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(dev);
-       struct drm_nouveau_getparam g;
-       int ret;
-
-       if (!nvdev || !value)
-               return -EINVAL;
-
-       g.param = param;
-       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GETPARAM,
-                                 &g, sizeof(g));
-       if (ret)
-               return ret;
-
-       *value = g.value;
-       return 0;
-}
-
-int
-nouveau_device_set_param(struct nouveau_device *dev,
-                        uint64_t param, uint64_t value)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(dev);
-       struct drm_nouveau_setparam s;
-       int ret;
-
-       if (!nvdev)
-               return -EINVAL;
-
-       s.param = param;
-       s.value = value;
-       ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_SETPARAM,
-                                 &s, sizeof(s));
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
diff --git a/nouveau/nouveau_device.h b/nouveau/nouveau_device.h
deleted file mode 100644 (file)
index c0d9333..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_DEVICE_H__
-#define __NOUVEAU_DEVICE_H__
-
-struct nouveau_device {
-       unsigned chipset;
-       uint64_t vm_vram_base;
-       uint64_t vm_vram_size;
-       uint64_t vm_gart_size;
-};
-
-#endif
diff --git a/nouveau/nouveau_drmif.h b/nouveau/nouveau_drmif.h
deleted file mode 100644 (file)
index ec226a2..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright 2008 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_DRMIF_H__
-#define __NOUVEAU_DRMIF_H__
-
-#include <stdint.h>
-#include <xf86drm.h>
-
-#include "nouveau_device.h"
-
-struct nouveau_device_priv {
-       struct nouveau_device base;
-
-       int fd;
-       drm_context_t ctx;
-       drmLock *lock;
-       int needs_close;
-       int has_bo_usage;
-};
-#define nouveau_device(n) ((struct nouveau_device_priv *)(n))
-
-int
-nouveau_device_open_existing(struct nouveau_device **, int close,
-                            int fd, drm_context_t ctx);
-
-int
-nouveau_device_open(struct nouveau_device **, const char *busid);
-
-void
-nouveau_device_close(struct nouveau_device **);
-
-int
-nouveau_device_get_param(struct nouveau_device *, uint64_t param, uint64_t *v);
-
-int
-nouveau_device_set_param(struct nouveau_device *, uint64_t param, uint64_t val);
-
-#endif
diff --git a/nouveau/nouveau_grobj.c b/nouveau/nouveau_grobj.c
deleted file mode 100644 (file)
index 36344b9..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include "nouveau_private.h"
-
-int
-nouveau_grobj_alloc(struct nouveau_channel *chan, uint32_t handle,
-                   int class, struct nouveau_grobj **grobj)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
-       struct nouveau_grobj_priv *nvgrobj;
-       struct drm_nouveau_grobj_alloc g;
-       int ret;
-
-       if (!nvdev || !grobj || *grobj)
-               return -EINVAL;
-
-       nvgrobj = calloc(1, sizeof(*nvgrobj));
-       if (!nvgrobj)
-               return -ENOMEM;
-       nvgrobj->base.channel = chan;
-       nvgrobj->base.handle  = handle;
-       nvgrobj->base.grclass = class;
-       nvgrobj->base.bound   = NOUVEAU_GROBJ_UNBOUND;
-       nvgrobj->base.subc    = -1;
-
-       g.channel = chan->id;
-       g.handle  = handle;
-       g.class   = class;
-       ret = drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GROBJ_ALLOC,
-                             &g, sizeof(g));
-       if (ret) {
-               nouveau_grobj_free((void *)&nvgrobj);
-               return ret;
-       }
-
-       *grobj = &nvgrobj->base;
-       return 0;
-}
-
-int
-nouveau_grobj_ref(struct nouveau_channel *chan, uint32_t handle,
-                 struct nouveau_grobj **grobj)
-{
-       struct nouveau_grobj_priv *nvgrobj;
-
-       if (!chan || !grobj || *grobj)
-               return -EINVAL;
-
-       nvgrobj = calloc(1, sizeof(struct nouveau_grobj_priv));
-       if (!nvgrobj)
-               return -ENOMEM;
-       nvgrobj->base.channel = chan;
-       nvgrobj->base.handle = handle;
-       nvgrobj->base.grclass = 0;
-
-       *grobj = &nvgrobj->base;
-       return 0;
-}
-
-void
-nouveau_grobj_free(struct nouveau_grobj **grobj)
-{
-       struct nouveau_device_priv *nvdev;
-       struct nouveau_channel_priv *chan;
-       struct nouveau_grobj_priv *nvgrobj;
-
-       if (!grobj || !*grobj)
-               return;
-       nvgrobj = nouveau_grobj(*grobj);
-       *grobj = NULL;
-
-
-       chan = nouveau_channel(nvgrobj->base.channel);
-       nvdev = nouveau_device(chan->base.device);
-
-       if (nvgrobj->base.grclass) {
-               struct drm_nouveau_gpuobj_free f;
-
-               FIRE_RING(&chan->base);
-               f.channel = chan->drm.channel;
-               f.handle  = nvgrobj->base.handle;
-               drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE,
-                               &f, sizeof(f)); 
-       }
-       if (nvgrobj->base.bound != NOUVEAU_GROBJ_UNBOUND)
-               chan->base.subc[nvgrobj->base.subc].gr = NULL;
-       free(nvgrobj);
-}
-
-void
-nouveau_grobj_autobind(struct nouveau_grobj *grobj)
-{
-       struct nouveau_channel *chan = grobj->channel;
-       struct nouveau_subchannel *subc = NULL;
-       int i;
-
-       for (i = 0; i < 8; i++) {
-               struct nouveau_subchannel *scc = &grobj->channel->subc[i];
-
-               if (scc->gr && scc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
-                       continue;
-
-               if (!subc || scc->sequence < subc->sequence)
-                       subc = scc;
-       }
-
-       if (subc->gr) {
-               subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
-               subc->gr->subc  = -1;
-       }
-
-       subc->gr = grobj;
-       subc->gr->bound = NOUVEAU_GROBJ_BOUND;
-       subc->gr->subc  = subc - &grobj->channel->subc[0];
-
-       WAIT_RING(chan, 2);
-       if (chan->device->chipset < 0xc0) {
-               OUT_RING (chan, (1 << 18) | (grobj->subc << 13));
-               OUT_RING (chan, grobj->handle);
-       } else {
-               OUT_RING (chan, (2 << 28) | (1 << 16) | (grobj->subc << 13));
-               OUT_RING (chan, grobj->grclass);
-       }
-}
-
diff --git a/nouveau/nouveau_grobj.h b/nouveau/nouveau_grobj.h
deleted file mode 100644 (file)
index 51ac7d9..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_GROBJ_H__
-#define __NOUVEAU_GROBJ_H__
-
-#include "nouveau_channel.h"
-
-struct nouveau_grobj {
-       struct nouveau_channel *channel;
-       int grclass;
-       uint32_t handle;
-
-       enum {
-               NOUVEAU_GROBJ_UNBOUND = 0,
-               NOUVEAU_GROBJ_BOUND = 1,
-               NOUVEAU_GROBJ_BOUND_EXPLICIT = 2
-       } bound;
-       int subc;
-};
-
-int nouveau_grobj_alloc(struct nouveau_channel *, uint32_t handle,
-                              int class, struct nouveau_grobj **);
-int nouveau_grobj_ref(struct nouveau_channel *, uint32_t handle,
-                            struct nouveau_grobj **);
-void nouveau_grobj_free(struct nouveau_grobj **);
-void nouveau_grobj_autobind(struct nouveau_grobj *);
-
-#endif
diff --git a/nouveau/nouveau_notifier.c b/nouveau/nouveau_notifier.c
deleted file mode 100644 (file)
index 513fa63..0000000
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-#include <sys/time.h>
-
-#include "nouveau_private.h"
-
-#define NOTIFIER(__v)                                                          \
-       struct nouveau_notifier_priv *nvnotify = nouveau_notifier(notifier);   \
-       volatile uint32_t *__v = (uint32_t *)((char *)nvnotify->map + (id * 32))
-
-int
-nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
-                      int count, struct nouveau_notifier **notifier)
-{
-       struct nouveau_notifier_priv *nvnotify;
-       int ret;
-
-       if (!chan || !notifier || *notifier)
-               return -EINVAL;
-
-       nvnotify = calloc(1, sizeof(struct nouveau_notifier_priv));
-       if (!nvnotify)
-               return -ENOMEM;
-       nvnotify->base.channel = chan;
-       nvnotify->base.handle  = handle;
-
-       nvnotify->drm.channel = chan->id;
-       nvnotify->drm.handle  = handle;
-       nvnotify->drm.size    = (count * 32);
-       if ((ret = drmCommandWriteRead(nouveau_device(chan->device)->fd,
-                                      DRM_NOUVEAU_NOTIFIEROBJ_ALLOC,
-                                      &nvnotify->drm,
-                                      sizeof(nvnotify->drm)))) {
-               nouveau_notifier_free((void *)&nvnotify);
-               return ret;
-       }
-
-       nvnotify->map = (char *)nouveau_channel(chan)->notifier_bo->map +
-                               nvnotify->drm.offset;
-       *notifier = &nvnotify->base;
-       return 0;
-}
-
-void
-nouveau_notifier_free(struct nouveau_notifier **notifier)
-{
-
-       struct nouveau_notifier_priv *nvnotify;
-       struct nouveau_channel_priv *nvchan;
-       struct nouveau_device_priv *nvdev;
-       struct drm_nouveau_gpuobj_free f;
-
-       if (!notifier || !*notifier)
-               return;
-       nvnotify = nouveau_notifier(*notifier);
-       *notifier = NULL;
-
-       nvchan = nouveau_channel(nvnotify->base.channel);
-       nvdev   = nouveau_device(nvchan->base.device);
-
-       FIRE_RING(&nvchan->base);
-
-       f.channel = nvchan->drm.channel;
-       f.handle  = nvnotify->base.handle;
-       drmCommandWrite(nvdev->fd, DRM_NOUVEAU_GPUOBJ_FREE, &f, sizeof(f));             
-       free(nvnotify);
-}
-
-void
-nouveau_notifier_reset(struct nouveau_notifier *notifier, int id)
-{
-       NOTIFIER(n);
-
-       n[NV_NOTIFY_TIME_0      /4] = 0x00000000;
-       n[NV_NOTIFY_TIME_1      /4] = 0x00000000;
-       n[NV_NOTIFY_RETURN_VALUE/4] = 0x00000000;
-       n[NV_NOTIFY_STATE       /4] = (NV_NOTIFY_STATE_STATUS_IN_PROCESS <<
-                                      NV_NOTIFY_STATE_STATUS_SHIFT);
-}
-
-uint32_t
-nouveau_notifier_status(struct nouveau_notifier *notifier, int id)
-{
-       NOTIFIER(n);
-
-       return n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
-}
-
-uint32_t
-nouveau_notifier_return_val(struct nouveau_notifier *notifier, int id)
-{
-       NOTIFIER(n);
-
-       return n[NV_NOTIFY_RETURN_VALUE/4];
-}
-
-static inline double
-gettime(void)
-{
-       struct timeval tv;
-
-       gettimeofday(&tv, NULL);
-       return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
-}
-
-int
-nouveau_notifier_wait_status(struct nouveau_notifier *notifier, int id,
-                            uint32_t status, double timeout)
-{
-       NOTIFIER(n);
-       double time = 0, t_start = gettime();
-
-       while (time <= timeout) {
-               uint32_t v;
-
-               v = n[NV_NOTIFY_STATE/4] >> NV_NOTIFY_STATE_STATUS_SHIFT;
-               if (v == status)
-                       return 0;
-
-               if (timeout)
-                       time = gettime() - t_start;
-       }
-
-       return -EBUSY;
-}
-
diff --git a/nouveau/nouveau_notifier.h b/nouveau/nouveau_notifier.h
deleted file mode 100644 (file)
index dbc6a3b..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_NOTIFIER_H__
-#define __NOUVEAU_NOTIFIER_H__
-
-#define NV_NOTIFIER_SIZE                                                      32
-#define NV_NOTIFY_TIME_0                                              0x00000000
-#define NV_NOTIFY_TIME_1                                              0x00000004
-#define NV_NOTIFY_RETURN_VALUE                                        0x00000008
-#define NV_NOTIFY_STATE                                               0x0000000C
-#define NV_NOTIFY_STATE_STATUS_MASK                                   0xFF000000
-#define NV_NOTIFY_STATE_STATUS_SHIFT                                          24
-#define NV_NOTIFY_STATE_STATUS_COMPLETED                                    0x00
-#define NV_NOTIFY_STATE_STATUS_IN_PROCESS                                   0x01
-#define NV_NOTIFY_STATE_ERROR_CODE_MASK                               0x0000FFFF
-#define NV_NOTIFY_STATE_ERROR_CODE_SHIFT                                       0
-
-struct nouveau_notifier {
-       struct nouveau_channel *channel;
-       uint32_t handle;
-};
-
-int
-nouveau_notifier_alloc(struct nouveau_channel *, uint32_t handle, int count,
-                      struct nouveau_notifier **);
-
-void
-nouveau_notifier_free(struct nouveau_notifier **);
-
-void
-nouveau_notifier_reset(struct nouveau_notifier *, int id);
-
-uint32_t
-nouveau_notifier_status(struct nouveau_notifier *, int id);
-
-uint32_t
-nouveau_notifier_return_val(struct nouveau_notifier *, int id);
-
-int
-nouveau_notifier_wait_status(struct nouveau_notifier *, int id, uint32_t status,
-                            double timeout);
-
-#endif
diff --git a/nouveau/nouveau_private.h b/nouveau/nouveau_private.h
deleted file mode 100644 (file)
index 124fe87..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_PRIVATE_H__
-#define __NOUVEAU_PRIVATE_H__
-
-#include <stdint.h>
-#include <xf86drm.h>
-#include <nouveau_drm.h>
-
-#include "nouveau_drmif.h"
-#include "nouveau_device.h"
-#include "nouveau_channel.h"
-#include "nouveau_grobj.h"
-#include "nouveau_notifier.h"
-#include "nouveau_bo.h"
-#include "nouveau_resource.h"
-#include "nouveau_pushbuf.h"
-#include "nouveau_reloc.h"
-
-#define CALPB_BUFFERS 3
-
-struct nouveau_pushbuf_priv {
-       uint32_t cal_suffix0;
-       uint32_t cal_suffix1;
-       struct nouveau_bo *buffer[CALPB_BUFFERS];
-       int current;
-       int current_offset;
-
-       unsigned *pushbuf;
-       unsigned size;
-
-       uint32_t *marker;
-       unsigned marker_offset;
-       unsigned marker_relocs;
-       unsigned marker_push;
-
-       struct drm_nouveau_gem_pushbuf_bo *buffers;
-       unsigned nr_buffers;
-       struct drm_nouveau_gem_pushbuf_reloc *relocs;
-       unsigned nr_relocs;
-       struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
-       unsigned nr_push;
-};
-#define nouveau_pushbuf(n) ((struct nouveau_pushbuf_priv *)(n))
-
-int
-nouveau_pushbuf_init(struct nouveau_channel *, int buf_size);
-void
-nouveau_pushbuf_fini(struct nouveau_channel *);
-
-struct nouveau_channel_priv {
-       struct nouveau_channel base;
-
-       struct drm_nouveau_channel_alloc drm;
-
-       struct nouveau_bo *notifier_bo;
-
-       struct nouveau_pushbuf_priv pb;
-};
-#define nouveau_channel(n) ((struct nouveau_channel_priv *)(n))
-
-struct nouveau_grobj_priv {
-       struct nouveau_grobj base;
-};
-#define nouveau_grobj(n) ((struct nouveau_grobj_priv *)(n))
-
-struct nouveau_notifier_priv {
-       struct nouveau_notifier base;
-
-       struct drm_nouveau_notifierobj_alloc drm;
-       volatile void *map;
-};
-#define nouveau_notifier(n) ((struct nouveau_notifier_priv *)(n))
-
-struct nouveau_bo_priv {
-       struct nouveau_bo base;
-       int refcount;
-
-       /* Buffer configuration + usage hints */
-       unsigned flags;
-       unsigned size;
-       unsigned align;
-       int user;
-
-       /* Tracking */
-       struct drm_nouveau_gem_pushbuf_bo *pending;
-       struct nouveau_channel *pending_channel;
-       int pending_refcnt;
-       int write_marker;
-
-       /* Userspace object */
-       void *sysmem;
-
-       /* Kernel object */
-       uint32_t global_handle;
-       drm_handle_t handle;
-       uint64_t map_handle;
-       int map_refcnt;
-       void *map;
-
-       /* Last known information from kernel on buffer status */
-       uint64_t offset;
-       uint32_t domain;
-};
-#define nouveau_bo(n) ((struct nouveau_bo_priv *)(n))
-
-int
-nouveau_bo_init(struct nouveau_device *);
-
-void
-nouveau_bo_takedown(struct nouveau_device *);
-
-struct drm_nouveau_gem_pushbuf_bo *
-nouveau_bo_emit_buffer(struct nouveau_channel *, struct nouveau_bo *);
-
-#endif
diff --git a/nouveau/nouveau_pushbuf.c b/nouveau/nouveau_pushbuf.c
deleted file mode 100644 (file)
index 59f60d9..0000000
+++ /dev/null
@@ -1,344 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "nouveau_private.h"
-
-#define PB_BUFMGR_DWORDS   (4096 / 2)
-#define PB_MIN_USER_DWORDS  2048
-
-static int
-nouveau_pushbuf_space(struct nouveau_channel *chan, unsigned min)
-{
-       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
-       struct nouveau_bo *bo;
-       int ret;
-
-       if (min < PB_MIN_USER_DWORDS)
-               min = PB_MIN_USER_DWORDS;
-
-       nvpb->current_offset = chan->cur - nvpb->pushbuf;
-       if (chan->cur + min + 2 <= chan->end)
-               return 0;
-
-       nvpb->current++;
-       if (nvpb->current == CALPB_BUFFERS)
-               nvpb->current = 0;
-       bo = nvpb->buffer[nvpb->current];
-
-       ret = nouveau_bo_map(bo, NOUVEAU_BO_WR);
-       if (ret)
-               return ret;
-
-       nvpb->size = (bo->size - 8) / 4;
-       nvpb->pushbuf = bo->map;
-       nvpb->current_offset = 0;
-
-       chan->cur = nvpb->pushbuf;
-       chan->end = nvpb->pushbuf + nvpb->size;
-
-       nouveau_bo_unmap(bo);
-       return 0;
-}
-
-static void
-nouveau_pushbuf_fini_call(struct nouveau_channel *chan)
-{
-       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
-       int i;
-
-       for (i = 0; i < CALPB_BUFFERS; i++)
-               nouveau_bo_ref(NULL, &nvpb->buffer[i]);
-       nvpb->pushbuf = NULL;
-}
-
-static int
-nouveau_pushbuf_init_call(struct nouveau_channel *chan, int buf_size)
-{
-       struct drm_nouveau_gem_pushbuf req;
-       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
-       struct nouveau_device *dev = chan->device;
-       uint32_t flags = 0;
-       int i, ret;
-
-       if (nvchan->drm.pushbuf_domains & NOUVEAU_GEM_DOMAIN_GART)
-               flags |= NOUVEAU_BO_GART;
-       else
-               flags |= NOUVEAU_BO_VRAM;
-
-       req.channel = chan->id;
-       req.nr_push = 0;
-       ret = drmCommandWriteRead(nouveau_device(dev)->fd,
-                                 DRM_NOUVEAU_GEM_PUSHBUF, &req, sizeof(req));
-       if (ret)
-               return ret;
-
-       for (i = 0; i < CALPB_BUFFERS; i++) {
-               ret = nouveau_bo_new(dev, flags | NOUVEAU_BO_MAP,
-                                    0, buf_size, &nvpb->buffer[i]);
-               if (ret) {
-                       nouveau_pushbuf_fini_call(chan);
-                       return ret;
-               }
-       }
-
-       nvpb->cal_suffix0 = req.suffix0;
-       nvpb->cal_suffix1 = req.suffix1;
-       return 0;
-}
-
-int
-nouveau_pushbuf_init(struct nouveau_channel *chan, int buf_size)
-{
-       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
-       int ret;
-
-       ret = nouveau_pushbuf_init_call(chan, buf_size);
-       if (ret)
-               return ret;
-
-       ret = nouveau_pushbuf_space(chan, 0);
-       if (ret)
-               return ret;
-
-       nvpb->buffers = calloc(NOUVEAU_GEM_MAX_BUFFERS,
-                              sizeof(struct drm_nouveau_gem_pushbuf_bo));
-       nvpb->relocs = calloc(NOUVEAU_GEM_MAX_RELOCS,
-                             sizeof(struct drm_nouveau_gem_pushbuf_reloc));
-       return 0;
-}
-
-void
-nouveau_pushbuf_fini(struct nouveau_channel *chan)
-{
-       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
-       nouveau_pushbuf_fini_call(chan);
-       free(nvpb->buffers);
-       free(nvpb->relocs);
-}
-
-static int
-nouveau_pushbuf_bo_add(struct nouveau_channel *chan, struct nouveau_bo *bo,
-                      unsigned offset, unsigned length)
-{
-       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
-       struct drm_nouveau_gem_pushbuf_push *p = &nvpb->push[nvpb->nr_push++];
-       struct drm_nouveau_gem_pushbuf_bo *pbbo;
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-
-       pbbo = nouveau_bo_emit_buffer(chan, bo);
-       if (!pbbo)
-               return -ENOMEM;
-       pbbo->valid_domains &= nvchan->drm.pushbuf_domains;
-       pbbo->read_domains |= nvchan->drm.pushbuf_domains;
-       nvbo->pending_refcnt++;
-
-       p->bo_index = pbbo - nvpb->buffers;
-       p->offset = offset;
-       p->length = length;
-       return 0;
-}
-
-int
-nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
-                      unsigned offset, unsigned length)
-{
-       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
-       int ret, len;
-
-       if ((AVAIL_RING(chan) + nvpb->current_offset) != nvpb->size) {
-               if (nvpb->cal_suffix0 || nvpb->cal_suffix1) {
-                       *(chan->cur++) = nvpb->cal_suffix0;
-                       *(chan->cur++) = nvpb->cal_suffix1;
-               }
-
-               len = (chan->cur - nvpb->pushbuf) - nvpb->current_offset;
-
-               ret = nouveau_pushbuf_bo_add(chan, nvpb->buffer[nvpb->current],
-                                            nvpb->current_offset * 4, len * 4);
-               if (ret)
-                       return ret;
-
-               nvpb->current_offset += len;
-       }
-
-       return bo ? nouveau_pushbuf_bo_add(chan, bo, offset, length) : 0;
-}
-
-static void
-nouveau_pushbuf_bo_unref(struct nouveau_pushbuf_priv *nvpb, int index)
-{
-       struct drm_nouveau_gem_pushbuf_bo *pbbo = &nvpb->buffers[index];
-       struct nouveau_bo *bo = (void *)(unsigned long)pbbo->user_priv;
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-
-       if (--nvbo->pending_refcnt)
-               return;
-
-       if (pbbo->presumed.valid == 0) {
-               nvbo->domain = pbbo->presumed.domain;
-               nvbo->offset = pbbo->presumed.offset;
-       }
-
-       nvbo->pending = NULL;
-       nouveau_bo_ref(NULL, &bo);
-
-       /* we only ever remove from the tail of the pending lists,
-        * so this is safe.
-        */
-       nvpb->nr_buffers--;
-}
-
-int
-nouveau_pushbuf_flush(struct nouveau_channel *chan, unsigned min)
-{
-       struct nouveau_device_priv *nvdev = nouveau_device(chan->device);
-       struct nouveau_channel_priv *nvchan = nouveau_channel(chan);
-       struct nouveau_pushbuf_priv *nvpb = &nvchan->pb;
-       struct drm_nouveau_gem_pushbuf req;
-       unsigned i;
-       int ret;
-
-       ret = nouveau_pushbuf_submit(chan, NULL, 0, 0);
-       if (ret)
-               return ret;
-
-       if (!nvpb->nr_push)
-               return 0;
-
-       req.channel = chan->id;
-       req.nr_push = nvpb->nr_push;
-       req.push = (uint64_t)(unsigned long)nvpb->push;
-       req.nr_buffers = nvpb->nr_buffers;
-       req.buffers = (uint64_t)(unsigned long)nvpb->buffers;
-       req.nr_relocs = nvpb->nr_relocs;
-       req.relocs = (uint64_t)(unsigned long)nvpb->relocs;
-       req.suffix0 = nvpb->cal_suffix0;
-       req.suffix1 = nvpb->cal_suffix1;
-
-       do {
-               ret = drmCommandWriteRead(nvdev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
-                                         &req, sizeof(req));
-       } while (ret == -EAGAIN);
-       nvpb->cal_suffix0 = req.suffix0;
-       nvpb->cal_suffix1 = req.suffix1;
-       nvdev->base.vm_vram_size = req.vram_available;
-       nvdev->base.vm_gart_size = req.gart_available;
-
-       /* Update presumed offset/domain for any buffers that moved.
-        * Dereference all buffers on validate list
-        */
-       for (i = 0; i < nvpb->nr_relocs; i++) {
-               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
-               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
-       }
-
-       for (i = 0; i < nvpb->nr_push; i++)
-               nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
-
-       nvpb->nr_buffers = 0;
-       nvpb->nr_relocs = 0;
-       nvpb->nr_push = 0;
-
-       /* Allocate space for next push buffer */
-       if (nouveau_pushbuf_space(chan, min))
-               assert(0);
-
-       if (chan->flush_notify)
-               chan->flush_notify(chan);
-
-       nvpb->marker = NULL;
-       return ret;
-}
-
-int
-nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
-                           unsigned wait_dwords, unsigned wait_relocs)
-{
-       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
-
-       if (AVAIL_RING(chan) < wait_dwords)
-               return nouveau_pushbuf_flush(chan, wait_dwords);
-
-       if (nvpb->nr_relocs + wait_relocs >= NOUVEAU_GEM_MAX_RELOCS)
-               return nouveau_pushbuf_flush(chan, wait_dwords);
-
-       nvpb->marker = chan->cur;
-       nvpb->marker_offset = nvpb->current_offset;
-       nvpb->marker_push = nvpb->nr_push;
-       nvpb->marker_relocs = nvpb->nr_relocs;
-       return 0;
-}
-
-void
-nouveau_pushbuf_marker_undo(struct nouveau_channel *chan)
-{
-       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
-       unsigned i;
-
-       if (!nvpb->marker)
-               return;
-
-       /* undo any relocs/buffers added to the list since last marker */
-       for (i = nvpb->marker_relocs; i < nvpb->nr_relocs; i++) {
-               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].bo_index);
-               nouveau_pushbuf_bo_unref(nvpb, nvpb->relocs[i].reloc_bo_index);
-       }
-       nvpb->nr_relocs = nvpb->marker_relocs;
-
-       for (i = nvpb->marker_push; i < nvpb->nr_push; i++)
-               nouveau_pushbuf_bo_unref(nvpb, nvpb->push[i].bo_index);
-       nvpb->nr_push = nvpb->marker_push;
-
-       /* reset pushbuf back to last marker */
-       chan->cur = nvpb->marker;
-       nvpb->current_offset = nvpb->marker_offset;
-       nvpb->marker = NULL;
-}
-
-int
-nouveau_pushbuf_emit_reloc(struct nouveau_channel *chan, void *ptr,
-                          struct nouveau_bo *bo, uint32_t data, uint32_t data2,
-                          uint32_t flags, uint32_t vor, uint32_t tor)
-{
-       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
-       int ret;
-
-       ret = nouveau_reloc_emit(chan, nvpb->buffer[nvpb->current],
-                                (char *)ptr - (char *)nvpb->pushbuf, ptr,
-                                bo, data, data2, flags, vor, tor);
-       if (ret)
-               return ret;
-
-       return 0;
-}
-
diff --git a/nouveau/nouveau_pushbuf.h b/nouveau/nouveau_pushbuf.h
deleted file mode 100644 (file)
index 2a98789..0000000
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_PUSHBUF_H__
-#define __NOUVEAU_PUSHBUF_H__
-
-#include <assert.h>
-#include <string.h>
-
-#include "nouveau_bo.h"
-#include "nouveau_grobj.h"
-
-int
-nouveau_pushbuf_flush(struct nouveau_channel *, unsigned min);
-
-int
-nouveau_pushbuf_marker_emit(struct nouveau_channel *chan,
-                           unsigned wait_dwords, unsigned wait_relocs);
-
-void
-nouveau_pushbuf_marker_undo(struct nouveau_channel *chan);
-
-int
-nouveau_pushbuf_emit_reloc(struct nouveau_channel *, void *ptr,
-                          struct nouveau_bo *, uint32_t data, uint32_t data2,
-                          uint32_t flags, uint32_t vor, uint32_t tor);
-
-int
-nouveau_pushbuf_submit(struct nouveau_channel *chan, struct nouveau_bo *bo,
-                      unsigned offset, unsigned length);
-
-/* Push buffer access macros */
-static __inline__ int
-MARK_RING(struct nouveau_channel *chan, unsigned dwords, unsigned relocs)
-{
-       return nouveau_pushbuf_marker_emit(chan, dwords, relocs);
-}
-
-static __inline__ void
-MARK_UNDO(struct nouveau_channel *chan)
-{
-       nouveau_pushbuf_marker_undo(chan);
-}
-
-static __inline__ void
-OUT_RING(struct nouveau_channel *chan, unsigned data)
-{
-       *(chan->cur++) = (data);
-}
-
-static __inline__ void
-OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned size)
-{
-       memcpy(chan->cur, data, size * 4);
-       chan->cur += size;
-}
-
-static __inline__ void
-OUT_RINGf(struct nouveau_channel *chan, float f)
-{
-       union { uint32_t i; float f; } c;
-       c.f = f;
-       OUT_RING(chan, c.i);
-}
-
-static __inline__ unsigned
-AVAIL_RING(struct nouveau_channel *chan)
-{
-       return chan->end - chan->cur;
-}
-
-static __inline__ void
-WAIT_RING(struct nouveau_channel *chan, unsigned size)
-{
-       if (chan->cur + size > chan->end)
-               nouveau_pushbuf_flush(chan, size);
-}
-
-static __inline__ void
-FIRE_RING(struct nouveau_channel *chan)
-{
-       nouveau_pushbuf_flush(chan, 0);
-}
-
-static __inline__ int
-OUT_RELOC(struct nouveau_channel *chan, struct nouveau_bo *bo,
-         unsigned data, unsigned flags, unsigned vor, unsigned tor)
-{
-       return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
-                                         data, 0, flags, vor, tor);
-}
-
-static __inline__ int
-OUT_RELOC2(struct nouveau_channel *chan, struct nouveau_bo *bo,
-          unsigned data, unsigned data2, unsigned flags,
-          unsigned vor, unsigned tor)
-{
-       return nouveau_pushbuf_emit_reloc(chan, chan->cur++, bo,
-                                         data, data2, flags, vor, tor);
-}
-
-/* Raw data + flags depending on FB/TT buffer */
-static __inline__ int
-OUT_RELOCd(struct nouveau_channel *chan, struct nouveau_bo *bo,
-          unsigned data, unsigned flags, unsigned vor, unsigned tor)
-{
-       return OUT_RELOC(chan, bo, data, flags | NOUVEAU_BO_OR, vor, tor);
-}
-
-/* FB/TT object handle */
-static __inline__ int
-OUT_RELOCo(struct nouveau_channel *chan, struct nouveau_bo *bo,
-          unsigned flags)
-{
-       return OUT_RELOC(chan, bo, 0, flags | NOUVEAU_BO_OR,
-                        chan->vram->handle, chan->gart->handle);
-}
-
-/* Low 32-bits of offset */
-static __inline__ int
-OUT_RELOCl(struct nouveau_channel *chan, struct nouveau_bo *bo,
-          unsigned delta, unsigned flags)
-{
-       return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_LOW, 0, 0);
-}
-
-/* Low 32-bits of offset + GPU linear access range info */
-static __inline__ int
-OUT_RELOCr(struct nouveau_channel *chan, struct nouveau_bo *bo,
-          unsigned delta, unsigned size, unsigned flags)
-{
-       return OUT_RELOC2(chan, bo, delta, size, flags | NOUVEAU_BO_LOW, 0, 0);
-}
-
-/* High 32-bits of offset */
-static __inline__ int
-OUT_RELOCh(struct nouveau_channel *chan, struct nouveau_bo *bo,
-          unsigned delta, unsigned flags)
-{
-       return OUT_RELOC(chan, bo, delta, flags | NOUVEAU_BO_HIGH, 0, 0);
-}
-
-#endif
diff --git a/nouveau/nouveau_reloc.c b/nouveau/nouveau_reloc.c
deleted file mode 100644 (file)
index cd219db..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2010 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <assert.h>
-
-#include "nouveau_private.h"
-
-static uint32_t
-nouveau_reloc_calc(struct drm_nouveau_gem_pushbuf_bo *pbbo,
-                  struct drm_nouveau_gem_pushbuf_reloc *r)
-{
-       uint32_t push = 0;
-
-       if (r->flags & NOUVEAU_GEM_RELOC_LOW)
-               push = (pbbo->presumed.offset + r->data);
-       else
-       if (r->flags & NOUVEAU_GEM_RELOC_HIGH)
-               push = (pbbo->presumed.offset + r->data) >> 32;
-       else
-               push = r->data;
-
-       if (r->flags & NOUVEAU_GEM_RELOC_OR) {
-               if (pbbo->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM)
-                       push |= r->vor;
-               else
-                       push |= r->tor;
-       }
-
-       return push;
-}
-
-int
-nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
-                  uint32_t reloc_offset, uint32_t *reloc_ptr,
-                  struct nouveau_bo *bo, uint32_t data, uint32_t data2,
-                  uint32_t flags, uint32_t vor, uint32_t tor)
-{
-       struct nouveau_pushbuf_priv *nvpb = &nouveau_channel(chan)->pb;
-       struct nouveau_bo_priv *nvbo = nouveau_bo(bo);
-       struct drm_nouveau_gem_pushbuf_reloc *r;
-       struct drm_nouveau_gem_pushbuf_bo *pbbo, *rpbbo;
-       uint32_t domains = 0;
-
-       if (nvpb->nr_relocs >= NOUVEAU_GEM_MAX_RELOCS) {
-               fprintf(stderr, "too many relocs!!\n");
-               return -ENOMEM;
-       }
-
-       if (nvbo->user && (flags & NOUVEAU_BO_WR)) {
-               fprintf(stderr, "write to user buffer!!\n");
-               return -EINVAL;
-       }
-
-       /* We're about to reloc a user buffer, better make sure we don't cause
-        * a double migration.
-        */
-       if (!(nvbo->flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM)))
-               nvbo->flags |= (flags & (NOUVEAU_BO_GART | NOUVEAU_BO_VRAM));
-
-       /* add buffer to validation list */
-       pbbo = nouveau_bo_emit_buffer(chan, bo);
-       if (!pbbo) {
-               fprintf(stderr, "buffer emit fail :(\n");
-               return -ENOMEM;
-       }
-       nouveau_bo(bo)->pending_refcnt++;
-
-       if (flags & (NOUVEAU_BO_VRAM | NOUVEAU_BO_GART)) {
-               if (flags & NOUVEAU_BO_VRAM)
-                       domains |= NOUVEAU_GEM_DOMAIN_VRAM;
-               if (flags & NOUVEAU_BO_GART)
-                       domains |= NOUVEAU_GEM_DOMAIN_GART;
-       } else
-               domains |= nvbo->domain;
-
-       if (!(pbbo->valid_domains & domains)) {
-               fprintf(stderr, "no valid domains remain!\n");
-               return -EINVAL;
-       }
-       pbbo->valid_domains &= domains;
-
-       assert(flags & NOUVEAU_BO_RDWR);
-       if (flags & NOUVEAU_BO_RD) {
-               pbbo->read_domains |= domains;
-       }
-       if (flags & NOUVEAU_BO_WR) {
-               pbbo->write_domains |= domains;
-               nvbo->write_marker = 1;
-       }
-
-       /* nvc0 gallium driver uses reloc_emit() with NULL target buffer
-        * to inform bufmgr of a buffer's use - however, we need something
-        * to track, so create a reloc for now, and hope it never triggers
-        * (it shouldn't, constant virtual address..)..
-        */
-       if (!reloc_bo) {
-               reloc_bo  = nvpb->buffer[nvpb->current];
-               reloc_offset = 0;
-               reloc_ptr = NULL;
-       }
-
-       /* add reloc target bo to validation list, and create the reloc */
-       rpbbo = nouveau_bo_emit_buffer(chan, reloc_bo);
-       if (!rpbbo)
-               return -ENOMEM;
-       nouveau_bo(reloc_bo)->pending_refcnt++;
-
-       r = nvpb->relocs + nvpb->nr_relocs++;
-       r->reloc_bo_index = rpbbo - nvpb->buffers;
-       r->reloc_bo_offset = reloc_offset;
-       r->bo_index = pbbo - nvpb->buffers;
-       r->flags = 0;
-       if (flags & NOUVEAU_BO_LOW)
-               r->flags |= NOUVEAU_GEM_RELOC_LOW;
-       if (flags & NOUVEAU_BO_HIGH)
-               r->flags |= NOUVEAU_GEM_RELOC_HIGH;
-       if (flags & NOUVEAU_BO_OR)
-               r->flags |= NOUVEAU_GEM_RELOC_OR;
-       r->data = data;
-       r->vor = vor;
-       r->tor = tor;
-
-       if (reloc_ptr) {
-               if (flags & NOUVEAU_BO_DUMMY)
-                       *reloc_ptr = 0;
-               else
-                       *reloc_ptr = nouveau_reloc_calc(pbbo, r);
-       }
-
-       return 0;
-}
-
diff --git a/nouveau/nouveau_reloc.h b/nouveau/nouveau_reloc.h
deleted file mode 100644 (file)
index 24ddb52..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2010 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_RELOC_H__
-#define __NOUVEAU_RELOC_H__
-
-int
-nouveau_reloc_emit(struct nouveau_channel *chan, struct nouveau_bo *reloc_bo,
-                  uint32_t reloc_offset, uint32_t *reloc_ptr,
-                  struct nouveau_bo *bo, uint32_t data, uint32_t data2,
-                  uint32_t flags, uint32_t vor, uint32_t tor);
-
-#endif
diff --git a/nouveau/nouveau_resource.c b/nouveau/nouveau_resource.c
deleted file mode 100644 (file)
index 7acaf7d..0000000
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include <stdlib.h>
-#include <errno.h>
-
-#include "nouveau_private.h"
-
-int
-nouveau_resource_init(struct nouveau_resource **heap,
-                     unsigned start, unsigned size)
-{
-       struct nouveau_resource *r;
-
-       r = calloc(1, sizeof(struct nouveau_resource));
-       if (!r)
-               return 1;
-
-       r->start = start;
-       r->size  = size;
-       *heap = r;
-       return 0;
-}
-
-void
-nouveau_resource_destroy(struct nouveau_resource **heap)
-{
-       if (!*heap)
-               return;
-       free(*heap);
-       *heap = NULL;
-}
-
-int
-nouveau_resource_alloc(struct nouveau_resource *heap, unsigned size, void *priv,
-                      struct nouveau_resource **res)
-{
-       struct nouveau_resource *r;
-
-       if (!heap || !size || !res || *res)
-               return 1;
-
-       while (heap) {
-               if (!heap->in_use && heap->size >= size) {
-                       r = calloc(1, sizeof(struct nouveau_resource));
-                       if (!r)
-                               return 1;
-
-                       r->start  = (heap->start + heap->size) - size;
-                       r->size   = size;
-                       r->in_use = 1;
-                       r->priv   = priv;
-
-                       heap->size -= size;
-
-                       r->next = heap->next;
-                       if (heap->next)
-                               heap->next->prev = r;
-                       r->prev = heap;
-                       heap->next = r;
-
-                       *res = r;
-                       return 0;
-               }
-                       
-               heap = heap->next;
-       }
-
-       return 1;
-}
-
-void
-nouveau_resource_free(struct nouveau_resource **res)
-{
-       struct nouveau_resource *r;
-
-       if (!res || !*res)
-               return;
-       r = *res;
-       *res = NULL;
-
-       r->in_use = 0;
-
-       if (r->next && !r->next->in_use) {
-               struct nouveau_resource *new = r->next;
-
-               new->prev = r->prev;
-               if (r->prev)
-                       r->prev->next = new;
-               new->size += r->size;
-               new->start = r->start;
-
-               free(r);
-               r = new;
-       }
-
-       if (r->prev && !r->prev->in_use) {
-               r->prev->next = r->next;
-               if (r->next)
-                       r->next->prev = r->prev;
-               r->prev->size += r->size;
-               free(r);
-       }
-       
-}
diff --git a/nouveau/nouveau_resource.h b/nouveau/nouveau_resource.h
deleted file mode 100644 (file)
index b760dfb..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NOUVEAU_RESOURCE_H__
-#define __NOUVEAU_RESOURCE_H__
-
-struct nouveau_resource {
-       struct nouveau_resource *prev;
-       struct nouveau_resource *next;
-
-       int in_use;
-       void *priv;
-
-       unsigned int start;
-       unsigned int size;
-};
-
-int
-nouveau_resource_init(struct nouveau_resource **heap, unsigned start,
-                     unsigned size);
-
-void
-nouveau_resource_destroy(struct nouveau_resource **heap);
-
-int
-nouveau_resource_alloc(struct nouveau_resource *heap, unsigned size, void *priv,
-                      struct nouveau_resource **);
-
-void
-nouveau_resource_free(struct nouveau_resource **);
-
-#endif
diff --git a/nouveau/nv04_pushbuf.h b/nouveau/nv04_pushbuf.h
deleted file mode 100644 (file)
index 586b284..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2007 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NV04_PUSHBUF_H__
-#define __NV04_PUSHBUF_H__
-
-#include "nouveau_pushbuf.h"
-
-static __inline__ void
-BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
-          unsigned mthd, unsigned size)
-{
-       if (gr->bound == NOUVEAU_GROBJ_UNBOUND)
-               nouveau_grobj_autobind(gr);
-       chan->subc[gr->subc].sequence = chan->subc_sequence++;
-
-       WAIT_RING(chan, size + 1);
-       OUT_RING(chan, (gr->subc << 13) | (size << 18) | mthd);
-}
-
-/* non-incrementing BEGIN_RING */
-static __inline__ void
-BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr,
-          unsigned mthd, unsigned size)
-{
-       BEGIN_RING(chan, gr, mthd | 0x40000000, size);
-}
-
-static __inline__ void
-BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
-{
-       struct nouveau_subchannel *subc = &gr->channel->subc[sc];
-
-       if (subc->gr) {
-               if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
-                       assert(0);
-               subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
-       }
-       subc->gr = gr;
-       subc->gr->subc = sc;
-       subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
-
-       BEGIN_RING(chan, gr, 0x0000, 1);
-       OUT_RING  (chan, gr->handle);
-}
-
-#endif
diff --git a/nouveau/nvc0_pushbuf.h b/nouveau/nvc0_pushbuf.h
deleted file mode 100644 (file)
index 40dc7e6..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2010 Nouveau Project
- *
- * 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:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
- * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
- * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __NVC0_PUSHBUF_H__
-#define __NVC0_PUSHBUF_H__
-
-#include "nouveau_pushbuf.h"
-
-#define SUBC_BIND(chan, gr) do {                                               \
-       if (gr->bound == NOUVEAU_GROBJ_UNBOUND)                                \
-               nouveau_grobj_autobind(gr);                                    \
-       chan->subc[gr->subc].sequence = chan->subc_sequence++;                 \
-} while (0)
-
-/* incremental methods */
-static __inline__ void
-BEGIN_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
-          unsigned mthd, unsigned size)
-{
-       SUBC_BIND(chan, gr);
-       WAIT_RING(chan, size + 1);
-       OUT_RING (chan, (0x2 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
-}
-
-/* non-incremental */
-static __inline__ void
-BEGIN_RING_NI(struct nouveau_channel *chan, struct nouveau_grobj *gr,
-             unsigned mthd, unsigned size)
-{
-       SUBC_BIND(chan, gr);
-       WAIT_RING(chan, size + 1);
-       OUT_RING (chan, (0x6 << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
-}
-
-/* increment-once */
-static __inline__ void
-BEGIN_RING_1I(struct nouveau_channel *chan, struct nouveau_grobj *gr,
-             unsigned mthd, unsigned size)
-{
-       SUBC_BIND(chan, gr);
-       WAIT_RING(chan, size + 1);
-       OUT_RING (chan, (0xa << 28) | (size << 16) | (gr->subc << 13) | (mthd >> 2));
-}
-
-/* inline-data */
-static __inline__ void
-IMMED_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr,
-          unsigned mthd, unsigned data)
-{
-       SUBC_BIND(chan, gr);
-       WAIT_RING(chan, 1);
-       OUT_RING (chan, (0x8 << 28) | (data << 16) | (gr->subc << 13) | (mthd >> 2));
-}
-
-static __inline__ void
-BIND_RING(struct nouveau_channel *chan, struct nouveau_grobj *gr, unsigned sc)
-{
-       struct nouveau_subchannel *subc = &gr->channel->subc[sc];
-
-       if (subc->gr) {
-               if (subc->gr->bound == NOUVEAU_GROBJ_BOUND_EXPLICIT)
-                       assert(0);
-               subc->gr->bound = NOUVEAU_GROBJ_UNBOUND;
-       }
-       subc->gr = gr;
-       subc->gr->subc = sc;
-       subc->gr->bound = NOUVEAU_GROBJ_BOUND_EXPLICIT;
-
-       BEGIN_RING(chan, gr, 0x0000, 1);
-       OUT_RING  (chan, gr->grclass);
-}
-
-#endif
diff --git a/nouveau/private.h b/nouveau/private.h
new file mode 100644 (file)
index 0000000..b409cc8
--- /dev/null
@@ -0,0 +1,122 @@
+#ifndef __NOUVEAU_LIBDRM_PRIVATE_H__
+#define __NOUVEAU_LIBDRM_PRIVATE_H__
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+#include "nouveau_drm.h"
+
+#include "nouveau.h"
+
+#ifdef DEBUG
+uint32_t nouveau_debug;
+#define dbg_on(lvl) (nouveau_debug & (1 << lvl))
+#define dbg(lvl, fmt, args...) do {                                            \
+       if (dbg_on((lvl)))                                                     \
+               fprintf(stderr, "nouveau: "fmt, ##args);                       \
+} while(0)
+#else
+#define dbg_on(lvl) (0)
+#define dbg(lvl, fmt, args...)
+#endif
+#define err(fmt, args...) fprintf(stderr, "nouveau: "fmt, ##args)
+
+struct nouveau_client_kref {
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       struct nouveau_pushbuf *push;
+};
+
+struct nouveau_client_priv {
+       struct nouveau_client base;
+       struct nouveau_client_kref *kref;
+       unsigned kref_nr;
+};
+
+static inline struct nouveau_client_priv *
+nouveau_client(struct nouveau_client *client)
+{
+       return (struct nouveau_client_priv *)client;
+}
+
+static inline struct drm_nouveau_gem_pushbuf_bo *
+cli_kref_get(struct nouveau_client *client, struct nouveau_bo *bo)
+{
+       struct nouveau_client_priv *pcli = nouveau_client(client);
+       struct drm_nouveau_gem_pushbuf_bo *kref = NULL;
+       if (pcli->kref_nr > bo->handle)
+               kref = pcli->kref[bo->handle].kref;
+       return kref;
+}
+
+static inline struct nouveau_pushbuf *
+cli_push_get(struct nouveau_client *client, struct nouveau_bo *bo)
+{
+       struct nouveau_client_priv *pcli = nouveau_client(client);
+       struct nouveau_pushbuf *push = NULL;
+       if (pcli->kref_nr > bo->handle)
+               push = pcli->kref[bo->handle].push;
+       return push;
+}
+
+static inline void
+cli_kref_set(struct nouveau_client *client, struct nouveau_bo *bo,
+            struct drm_nouveau_gem_pushbuf_bo *kref,
+            struct nouveau_pushbuf *push)
+{
+       struct nouveau_client_priv *pcli = nouveau_client(client);
+       if (pcli->kref_nr <= bo->handle) {
+               pcli->kref = realloc(pcli->kref,
+                                    sizeof(*pcli->kref) * bo->handle * 2);
+               while (pcli->kref_nr < bo->handle * 2) {
+                       pcli->kref[pcli->kref_nr].kref = NULL;
+                       pcli->kref[pcli->kref_nr].push = NULL;
+                       pcli->kref_nr++;
+               }
+       }
+       pcli->kref[bo->handle].kref = kref;
+       pcli->kref[bo->handle].push = push;
+}
+
+struct nouveau_bo_priv {
+       struct nouveau_bo base;
+       struct nouveau_list head;
+       atomic_t refcnt;
+       uint64_t map_handle;
+       uint32_t name;
+       uint32_t access;
+};
+
+static inline struct nouveau_bo_priv *
+nouveau_bo(struct nouveau_bo *bo)
+{
+       return (struct nouveau_bo_priv *)bo;
+}
+
+struct nouveau_device_priv {
+       struct nouveau_device base;
+       int close;
+       atomic_t lock;
+       struct nouveau_list bo_list;
+       uint32_t *client;
+       int nr_client;
+       bool have_bo_usage;
+};
+
+static inline struct nouveau_device_priv *
+nouveau_device(struct nouveau_device *dev)
+{
+       return (struct nouveau_device_priv *)dev;
+}
+
+int
+nouveau_device_open_existing(struct nouveau_device **, int, int, drm_context_t);
+
+/* abi16.c */
+int  abi16_chan_nv04(struct nouveau_object *);
+int  abi16_chan_nvc0(struct nouveau_object *);
+int  abi16_engobj(struct nouveau_object *);
+int  abi16_ntfy(struct nouveau_object *);
+void abi16_bo_info(struct nouveau_bo *, struct drm_nouveau_gem_info *);
+int  abi16_bo_init(struct nouveau_bo *, uint32_t alignment,
+                  union nouveau_bo_config *);
+
+#endif
diff --git a/nouveau/pushbuf.c b/nouveau/pushbuf.c
new file mode 100644 (file)
index 0000000..7b9dbaa
--- /dev/null
@@ -0,0 +1,771 @@
+/*
+ * Copyright 2012 Red Hat Inc.
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) 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.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include <xf86drm.h>
+#include <xf86atomic.h>
+#include "libdrm_lists.h"
+#include "nouveau_drm.h"
+
+#include "nouveau.h"
+#include "private.h"
+
+struct nouveau_pushbuf_krec {
+       struct nouveau_pushbuf_krec *next;
+       struct drm_nouveau_gem_pushbuf_bo buffer[NOUVEAU_GEM_MAX_BUFFERS];
+       struct drm_nouveau_gem_pushbuf_reloc reloc[NOUVEAU_GEM_MAX_RELOCS];
+       struct drm_nouveau_gem_pushbuf_push push[NOUVEAU_GEM_MAX_PUSH];
+       int nr_buffer;
+       int nr_reloc;
+       int nr_push;
+       uint64_t vram_used;
+       uint64_t gart_used;
+};
+
+struct nouveau_pushbuf_priv {
+       struct nouveau_pushbuf base;
+       struct nouveau_pushbuf_krec *list;
+       struct nouveau_pushbuf_krec *krec;
+       struct nouveau_list bctx_list;
+       struct nouveau_bo *bo;
+       uint32_t type;
+       uint32_t suffix0;
+       uint32_t suffix1;
+       uint32_t *ptr;
+       uint32_t *bgn;
+       int bo_next;
+       int bo_nr;
+       struct nouveau_bo *bos[];
+};
+
+static inline struct nouveau_pushbuf_priv *
+nouveau_pushbuf(struct nouveau_pushbuf *push)
+{
+       return (struct nouveau_pushbuf_priv *)push;
+}
+
+static int pushbuf_validate(struct nouveau_pushbuf *, bool);
+static int pushbuf_flush(struct nouveau_pushbuf *);
+
+static bool
+pushbuf_kref_fits(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+                 uint32_t *domains)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct nouveau_device *dev = push->client->device;
+       struct nouveau_bo *kbo;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       int i;
+
+       /* VRAM is the only valid domain.  GART and VRAM|GART buffers
+        * are all accounted to GART, so if this doesn't fit in VRAM
+        * straight up, a flush is needed.
+        */
+       if (*domains == NOUVEAU_GEM_DOMAIN_VRAM) {
+               if (krec->vram_used + bo->size > dev->vram_limit)
+                       return false;
+               krec->vram_used += bo->size;
+               return true;
+       }
+
+       /* GART or VRAM|GART buffer.  Account both of these buffer types
+        * to GART only for the moment, which simplifies things.  If the
+        * buffer can fit already, we're done here.
+        */
+       if (krec->gart_used + bo->size <= dev->gart_limit) {
+               krec->gart_used += bo->size;
+               return true;
+       }
+
+       /* Ran out of GART space, if it's a VRAM|GART buffer and it'll
+        * fit into available VRAM, turn it into a VRAM buffer
+        */
+       if ((*domains & NOUVEAU_GEM_DOMAIN_VRAM) &&
+           krec->vram_used + bo->size <= dev->vram_limit) {
+               *domains &= NOUVEAU_GEM_DOMAIN_VRAM;
+               krec->vram_used += bo->size;
+               return true;
+       }
+
+       /* Still couldn't fit the buffer in anywhere, so as a last resort;
+        * scan the buffer list for VRAM|GART buffers and turn them into
+        * VRAM buffers until we have enough space in GART for this one
+        */
+       kref = krec->buffer;
+       for (i = 0; i < krec->nr_buffer; i++, kref++) {
+               if (!(kref->valid_domains & NOUVEAU_GEM_DOMAIN_GART))
+                       continue;
+
+               kbo = (void *)(unsigned long)kref->user_priv;
+               if (!(kref->valid_domains & NOUVEAU_GEM_DOMAIN_VRAM) ||
+                   krec->vram_used + kbo->size > dev->vram_limit)
+                       continue;
+
+               kref->valid_domains &= NOUVEAU_GEM_DOMAIN_VRAM;
+               krec->gart_used -= kbo->size;
+               krec->vram_used += kbo->size;
+               if (krec->gart_used + bo->size <= dev->gart_limit) {
+                       krec->gart_used += bo->size;
+                       return true;
+               }
+       }
+
+       /* Couldn't resolve a placement, need to force a flush */
+       return false;
+}
+
+static struct drm_nouveau_gem_pushbuf_bo *
+pushbuf_kref(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+            uint32_t flags)
+{
+       struct nouveau_device *dev = push->client->device;
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct nouveau_pushbuf *fpush;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       uint32_t domains, domains_wr, domains_rd;
+
+       domains = 0;
+       if (flags & NOUVEAU_BO_VRAM)
+               domains |= NOUVEAU_GEM_DOMAIN_VRAM;
+       if (flags & NOUVEAU_BO_GART)
+               domains |= NOUVEAU_GEM_DOMAIN_GART;
+       domains_wr = domains * !!(flags & NOUVEAU_BO_WR);
+       domains_rd = domains * !!(flags & NOUVEAU_BO_RD);
+
+       /* if buffer is referenced on another pushbuf that is owned by the
+        * same client, we need to flush the other pushbuf first to ensure
+        * the correct ordering of commands
+        */
+       fpush = cli_push_get(push->client, bo);
+       if (fpush && fpush != push)
+               pushbuf_flush(fpush);
+
+       kref = cli_kref_get(push->client, bo);
+       if (kref) {
+               /* possible conflict in memory types - flush and retry */
+               if (!(kref->valid_domains & domains))
+                       return NULL;
+
+               /* VRAM|GART buffer turning into a VRAM buffer.  Make sure
+                * it'll fit in VRAM and force a flush if not.
+                */
+               if ((kref->valid_domains  & NOUVEAU_GEM_DOMAIN_GART) &&
+                   (            domains == NOUVEAU_GEM_DOMAIN_VRAM)) {
+                       if (krec->vram_used + bo->size > dev->vram_limit)
+                               return NULL;
+                       krec->vram_used += bo->size;
+                       krec->gart_used -= bo->size;
+               }
+
+               kref->valid_domains &= domains;
+               kref->write_domains |= domains_wr;
+               kref->read_domains  |= domains_rd;
+       } else {
+               if (krec->nr_buffer == NOUVEAU_GEM_MAX_BUFFERS ||
+                   !pushbuf_kref_fits(push, bo, &domains))
+                       return NULL;
+
+               kref = &krec->buffer[krec->nr_buffer++];
+               kref->user_priv = (unsigned long)bo;
+               kref->handle = bo->handle;
+               kref->valid_domains = domains;
+               kref->write_domains = domains_wr;
+               kref->read_domains = domains_rd;
+               kref->presumed.valid = 1;
+               kref->presumed.offset = bo->offset;
+               if (bo->flags & NOUVEAU_BO_VRAM)
+                       kref->presumed.domain = NOUVEAU_GEM_DOMAIN_VRAM;
+               else
+                       kref->presumed.domain = NOUVEAU_GEM_DOMAIN_GART;
+
+               cli_kref_set(push->client, bo, kref, push);
+               atomic_inc(&nouveau_bo(bo)->refcnt);
+       }
+
+       return kref;
+}
+
+static uint32_t
+pushbuf_krel(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+            uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct drm_nouveau_gem_pushbuf_reloc *krel;
+       struct drm_nouveau_gem_pushbuf_bo *pkref;
+       struct drm_nouveau_gem_pushbuf_bo *bkref;
+       uint32_t reloc = data;
+
+       pkref = cli_kref_get(push->client, nvpb->bo);
+       bkref = cli_kref_get(push->client, bo);
+       krel  = &krec->reloc[krec->nr_reloc++];
+
+       krel->reloc_bo_index = pkref - krec->buffer;
+       krel->reloc_bo_offset = (push->cur - nvpb->ptr) * 4;
+       krel->bo_index = bkref - krec->buffer;
+       krel->flags = 0;
+       krel->data = data;
+       krel->vor = vor;
+       krel->tor = tor;
+
+       if (flags & NOUVEAU_BO_LOW) {
+               reloc = (bkref->presumed.offset + data);
+               krel->flags |= NOUVEAU_GEM_RELOC_LOW;
+       } else
+       if (flags & NOUVEAU_BO_HIGH) {
+               reloc = (bkref->presumed.offset + data) >> 32;
+               krel->flags |= NOUVEAU_GEM_RELOC_HIGH;
+       }
+       if (flags & NOUVEAU_BO_OR) {
+               if (bkref->presumed.domain & NOUVEAU_GEM_DOMAIN_VRAM)
+                       reloc |= vor;
+               else
+                       reloc |= tor;
+               krel->flags |= NOUVEAU_GEM_RELOC_OR;
+       }
+
+       return reloc;
+}
+
+static void
+pushbuf_dump(struct nouveau_pushbuf_krec *krec, int krec_id, int chid)
+{
+       struct drm_nouveau_gem_pushbuf_reloc *krel;
+       struct drm_nouveau_gem_pushbuf_push *kpsh;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       struct nouveau_bo *bo;
+       uint32_t *bgn, *end;
+       int i;
+
+       err("ch%d: krec %d pushes %d bufs %d relocs %d\n", chid,
+           krec_id, krec->nr_push, krec->nr_buffer, krec->nr_reloc);
+
+       kref = krec->buffer;
+       for (i = 0; i < krec->nr_buffer; i++, kref++) {
+               err("ch%d: buf %08x %08x %08x %08x %08x\n", chid, i,
+                   kref->handle, kref->valid_domains,
+                   kref->read_domains, kref->write_domains);
+       }
+
+       krel = krec->reloc;
+       for (i = 0; i < krec->nr_reloc; i++, krel++) {
+               err("ch%d: rel %08x %08x %08x %08x %08x %08x %08x\n",
+                   chid, krel->reloc_bo_index, krel->reloc_bo_offset,
+                   krel->bo_index, krel->flags, krel->data,
+                   krel->vor, krel->tor);
+       }
+
+       kpsh = krec->push;
+       for (i = 0; i < krec->nr_push; i++, kpsh++) {
+               kref = krec->buffer + kpsh->bo_index;
+               bo = (void *)(unsigned long)kref->user_priv;
+               bgn = (uint32_t *)((char *)bo->map + kpsh->offset);
+               end = bgn + (kpsh->length /4);
+
+               err("ch%d: psh %08x %010llx %010llx\n", chid, kpsh->bo_index,
+                   (unsigned long long)kpsh->offset,
+                   (unsigned long long)(kpsh->offset + kpsh->length));
+               while (bgn < end)
+                       err("\t0x%08x\n", *bgn++);
+       }
+}
+
+static int
+pushbuf_submit(struct nouveau_pushbuf *push, struct nouveau_object *chan)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->list;
+       struct nouveau_device *dev = push->client->device;
+       struct drm_nouveau_gem_pushbuf_bo_presumed *info;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       struct drm_nouveau_gem_pushbuf req;
+       struct nouveau_fifo *fifo = chan->data;
+       struct nouveau_bo *bo;
+       int krec_id = 0;
+       int ret = 0, i;
+
+       if (chan->oclass != NOUVEAU_FIFO_CHANNEL_CLASS)
+               return -EINVAL;
+
+       if (push->kick_notify)
+               push->kick_notify(push);
+
+       nouveau_pushbuf_data(push, NULL, 0, 0);
+
+       while (krec && krec->nr_push) {
+               req.channel = fifo->channel;
+               req.nr_buffers = krec->nr_buffer;
+               req.buffers = (uint64_t)(unsigned long)krec->buffer;
+               req.nr_relocs = krec->nr_reloc;
+               req.nr_push = krec->nr_push;
+               req.relocs = (uint64_t)(unsigned long)krec->reloc;
+               req.push = (uint64_t)(unsigned long)krec->push;
+               req.suffix0 = nvpb->suffix0;
+               req.suffix1 = nvpb->suffix1;
+
+               if (dbg_on(0))
+                       pushbuf_dump(krec, krec_id++, fifo->channel);
+
+#ifndef SIMULATE
+               ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
+                                         &req, sizeof(req));
+               nvpb->suffix0 = req.suffix0;
+               nvpb->suffix1 = req.suffix1;
+               dev->vram_limit = (req.vram_available * 80) / 100;
+               dev->gart_limit = (req.gart_available * 80) / 100;
+#else
+               if (dbg_on(31))
+                       ret = -EINVAL;
+#endif
+
+               if (ret) {
+                       err("kernel rejected pushbuf: %s\n", strerror(-ret));
+                       pushbuf_dump(krec, krec_id++, fifo->channel);
+                       break;
+               }
+
+               kref = krec->buffer;
+               for (i = 0; i < krec->nr_buffer; i++, kref++) {
+                       bo = (void *)(unsigned long)kref->user_priv;
+
+                       info = &kref->presumed;
+                       if (!info->valid) {
+                               bo->flags &= ~NOUVEAU_BO_APER;
+                               if (info->domain == NOUVEAU_GEM_DOMAIN_VRAM)
+                                       bo->flags |= NOUVEAU_BO_VRAM;
+                               else
+                                       bo->flags |= NOUVEAU_BO_GART;
+                               bo->offset = info->offset;
+                       }
+
+                       if (kref->write_domains)
+                               nouveau_bo(bo)->access |= NOUVEAU_BO_WR;
+                       if (kref->read_domains)
+                               nouveau_bo(bo)->access |= NOUVEAU_BO_RD;
+               }
+
+               krec = krec->next;
+       }
+
+       return ret;
+}
+
+static int
+pushbuf_flush(struct nouveau_pushbuf *push)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       struct nouveau_bufctx *bctx, *btmp;
+       struct nouveau_bo *bo;
+       int ret = 0, i;
+
+       if (push->channel) {
+               ret = pushbuf_submit(push, push->channel);
+       } else {
+               nouveau_pushbuf_data(push, NULL, 0, 0);
+               krec->next = malloc(sizeof(*krec));
+               nvpb->krec = krec->next;
+       }
+
+       kref = krec->buffer;
+       for (i = 0; i < krec->nr_buffer; i++, kref++) {
+               bo = (void *)(unsigned long)kref->user_priv;
+               cli_kref_set(push->client, bo, NULL, NULL);
+               if (push->channel)
+                       nouveau_bo_ref(NULL, &bo);
+       }
+
+       krec = nvpb->krec;
+       krec->vram_used = 0;
+       krec->gart_used = 0;
+       krec->nr_buffer = 0;
+       krec->nr_reloc = 0;
+       krec->nr_push = 0;
+
+       DRMLISTFOREACHENTRYSAFE(bctx, btmp, &nvpb->bctx_list, head) {
+               DRMLISTJOIN(&bctx->current, &bctx->pending);
+               DRMINITLISTHEAD(&bctx->current);
+               DRMLISTDELINIT(&bctx->head);
+       }
+
+       return ret;
+}
+
+static void
+pushbuf_refn_fail(struct nouveau_pushbuf *push, int sref, int srel)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+
+       kref = krec->buffer + sref;
+       while (krec->nr_buffer-- > sref) {
+               struct nouveau_bo *bo = (void *)(unsigned long)kref->user_priv;
+               cli_kref_set(push->client, bo, NULL, NULL);
+               nouveau_bo_ref(NULL, &bo);
+               kref++;
+       }
+       krec->nr_buffer = sref;
+       krec->nr_reloc = srel;
+}
+
+static int
+pushbuf_refn(struct nouveau_pushbuf *push, bool retry,
+            struct nouveau_pushbuf_refn *refs, int nr)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       int sref = krec->nr_buffer;
+       int ret = 0, i;
+
+       for (i = 0; i < nr; i++) {
+               kref = pushbuf_kref(push, refs[i].bo, refs[i].flags);
+               if (!kref) {
+                       ret = -ENOSPC;
+                       break;
+               }
+       }
+
+       if (ret) {
+               pushbuf_refn_fail(push, sref, krec->nr_reloc);
+               if (retry) {
+                       pushbuf_flush(push);
+                       nouveau_pushbuf_space(push, 0, 0, 0);
+                       return pushbuf_refn(push, false, refs, nr);
+               }
+       }
+
+       return ret;
+}
+
+static int
+pushbuf_validate(struct nouveau_pushbuf *push, bool retry)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       struct nouveau_bufctx *bctx = push->bufctx;
+       struct nouveau_bufref *bref;
+       int relocs = bctx ? bctx->relocs * 2: 0;
+       int sref, srel, ret;
+
+       ret = nouveau_pushbuf_space(push, relocs, relocs, 0);
+       if (ret || bctx == NULL)
+               return ret;
+
+       sref = krec->nr_buffer;
+       srel = krec->nr_reloc;
+
+       DRMLISTDEL(&bctx->head);
+       DRMLISTADD(&bctx->head, &nvpb->bctx_list);
+
+       DRMLISTFOREACHENTRY(bref, &bctx->pending, thead) {
+               kref = pushbuf_kref(push, bref->bo, bref->flags);
+               if (!kref) {
+                       ret = -ENOSPC;
+                       break;
+               }
+
+               if (bref->packet) {
+                       pushbuf_krel(push, bref->bo, bref->packet, 0, 0, 0);
+                       *push->cur++ = 0;
+                       pushbuf_krel(push, bref->bo, bref->data, bref->flags,
+                                          bref->vor, bref->tor);
+                       *push->cur++ = 0;
+               }
+       }
+
+       DRMLISTJOIN(&bctx->pending, &bctx->current);
+       DRMINITLISTHEAD(&bctx->pending);
+
+       if (ret) {
+               pushbuf_refn_fail(push, sref, srel);
+               if (retry) {
+                       pushbuf_flush(push);
+                       return pushbuf_validate(push, false);
+               }
+       }
+
+       return 0;
+}
+
+int
+nouveau_pushbuf_new(struct nouveau_client *client, struct nouveau_object *chan,
+                   int nr, uint32_t size, bool immediate,
+                   struct nouveau_pushbuf **ppush)
+{
+       struct nouveau_device *dev = client->device;
+       struct nouveau_fifo *fifo = chan->data;
+       struct nouveau_pushbuf_priv *nvpb;
+       struct nouveau_pushbuf *push;
+       struct drm_nouveau_gem_pushbuf req;
+       int ret;
+
+       if (chan->oclass != NOUVEAU_FIFO_CHANNEL_CLASS)
+               return -EINVAL;
+
+       /* nop pushbuf call, to get the current "return to main" sequence
+        * we need to append to the pushbuf on early chipsets
+        */
+       req.channel = fifo->channel;
+       req.nr_push = 0;
+       ret = drmCommandWriteRead(dev->fd, DRM_NOUVEAU_GEM_PUSHBUF,
+                                 &req, sizeof(req));
+       if (ret)
+               return ret;
+
+       nvpb = calloc(1, sizeof(*nvpb) + nr * sizeof(*nvpb->bos));
+       if (!nvpb)
+               return -ENOMEM;
+
+#ifndef SIMULATE
+       nvpb->suffix0 = req.suffix0;
+       nvpb->suffix1 = req.suffix1;
+#else
+       nvpb->suffix0 = 0xffffffff;
+       nvpb->suffix1 = 0xffffffff;
+#endif
+       nvpb->krec = calloc(1, sizeof(*nvpb->krec));
+       nvpb->list = nvpb->krec;
+       if (!nvpb->krec) {
+               free(nvpb);
+               return -ENOMEM;
+       }
+
+       push = &nvpb->base;
+       push->client = client;
+       push->channel = immediate ? chan : NULL;
+       push->flags = NOUVEAU_BO_RD;
+       if (fifo->pushbuf & NOUVEAU_GEM_DOMAIN_VRAM) {
+               push->flags |= NOUVEAU_BO_VRAM;
+               nvpb->type   = NOUVEAU_BO_VRAM;
+       }
+       if (fifo->pushbuf & NOUVEAU_GEM_DOMAIN_GART) {
+               push->flags |= NOUVEAU_BO_GART;
+               nvpb->type   = NOUVEAU_BO_GART;
+       }
+       nvpb->type |= NOUVEAU_BO_MAP;
+
+       for (nvpb->bo_nr = 0; nvpb->bo_nr < nr; nvpb->bo_nr++) {
+               ret = nouveau_bo_new(client->device, nvpb->type, 0, size,
+                                    NULL, &nvpb->bos[nvpb->bo_nr]);
+               if (ret) {
+                       nouveau_pushbuf_del(&push);
+                       return ret;
+               }
+       }
+
+       DRMINITLISTHEAD(&nvpb->bctx_list);
+       *ppush = push;
+       return 0;
+}
+
+void
+nouveau_pushbuf_del(struct nouveau_pushbuf **ppush)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(*ppush);
+       if (nvpb) {
+               struct drm_nouveau_gem_pushbuf_bo *kref;
+               struct nouveau_pushbuf_krec *krec;
+               while ((krec = nvpb->list)) {
+                       kref = krec->buffer;
+                       while (krec->nr_buffer--) {
+                               unsigned long priv = kref++->user_priv;
+                               struct nouveau_bo *bo = (void *)priv;
+                               cli_kref_set(nvpb->base.client, bo, NULL, NULL);
+                               nouveau_bo_ref(NULL, &bo);
+                       }
+                       nvpb->list = krec->next;
+                       free(krec);
+               }
+               while (nvpb->bo_nr--)
+                       nouveau_bo_ref(NULL, &nvpb->bos[nvpb->bo_nr]);
+               nouveau_bo_ref(NULL, &nvpb->bo);
+               free(nvpb);
+       }
+       *ppush = NULL;
+}
+
+struct nouveau_bufctx *
+nouveau_pushbuf_bufctx(struct nouveau_pushbuf *push, struct nouveau_bufctx *ctx)
+{
+       struct nouveau_bufctx *prev = push->bufctx;
+       push->bufctx = ctx;
+       return prev;
+}
+
+int
+nouveau_pushbuf_space(struct nouveau_pushbuf *push,
+                     uint32_t dwords, uint32_t relocs, uint32_t pushes)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct nouveau_client *client = push->client;
+       struct nouveau_bo *bo = NULL;
+       bool flushed = false;
+       int ret = 0;
+
+       /* switch to next buffer if insufficient space in the current one */
+       if (push->cur + dwords >= push->end) {
+               if (nvpb->bo_next < nvpb->bo_nr) {
+                       nouveau_bo_ref(nvpb->bos[nvpb->bo_next++], &bo);
+                       if (nvpb->bo_next == nvpb->bo_nr && push->channel)
+                               nvpb->bo_next = 0;
+               } else {
+                       ret = nouveau_bo_new(client->device, nvpb->type, 0,
+                                            nvpb->bos[0]->size, NULL, &bo);
+                       if (ret)
+                               return ret;
+               }
+       }
+
+       /* make sure there's always enough space to queue up the pending
+        * data in the pushbuf proper
+        */
+       pushes++;
+
+       /* need to flush if we've run out of space on an immediate pushbuf,
+        * if the new buffer won't fit, or if the kernel push/reloc limits
+        * have been hit
+        */
+       if ((bo && ( push->channel ||
+                   !pushbuf_kref(push, bo, push->flags))) ||
+           krec->nr_reloc + relocs >= NOUVEAU_GEM_MAX_RELOCS ||
+           krec->nr_push + pushes >= NOUVEAU_GEM_MAX_PUSH) {
+               if (nvpb->bo && krec->nr_buffer)
+                       pushbuf_flush(push);
+               flushed = true;
+       }
+
+       /* if necessary, switch to new buffer */
+       if (bo) {
+               ret = nouveau_bo_map(bo, NOUVEAU_BO_WR, push->client);
+               if (ret)
+                       return ret;
+
+               nouveau_pushbuf_data(push, NULL, 0, 0);
+               nouveau_bo_ref(bo, &nvpb->bo);
+               nouveau_bo_ref(NULL, &bo);
+
+               nvpb->bgn = nvpb->bo->map;
+               nvpb->ptr = nvpb->bgn;
+               push->cur = nvpb->bgn;
+               push->end = push->cur + (nvpb->bo->size / 4);
+               push->end -= 2 + push->rsvd_kick; /* space for suffix */
+       }
+
+       pushbuf_kref(push, nvpb->bo, push->flags);
+       return flushed ? pushbuf_validate(push, false) : 0;
+}
+
+void
+nouveau_pushbuf_data(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+                    uint64_t offset, uint64_t length)
+{
+       struct nouveau_pushbuf_priv *nvpb = nouveau_pushbuf(push);
+       struct nouveau_pushbuf_krec *krec = nvpb->krec;
+       struct drm_nouveau_gem_pushbuf_push *kpsh;
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+
+       if (bo != nvpb->bo && nvpb->bgn != push->cur) {
+               if (nvpb->suffix0 || nvpb->suffix1) {
+                       *push->cur++ = nvpb->suffix0;
+                       *push->cur++ = nvpb->suffix1;
+               }
+
+               nouveau_pushbuf_data(push, nvpb->bo,
+                                    (nvpb->bgn - nvpb->ptr) * 4,
+                                    (push->cur - nvpb->bgn) * 4);
+               nvpb->bgn = push->cur;
+       }
+
+       if (bo) {
+               kref = cli_kref_get(push->client, bo);
+               kpsh = &krec->push[krec->nr_push++];
+               kpsh->bo_index = kref - krec->buffer;
+               kpsh->offset   = offset;
+               kpsh->length   = length;
+       }
+}
+
+int
+nouveau_pushbuf_refn(struct nouveau_pushbuf *push,
+                    struct nouveau_pushbuf_refn *refs, int nr)
+{
+       return pushbuf_refn(push, true, refs, nr);
+}
+
+void
+nouveau_pushbuf_reloc(struct nouveau_pushbuf *push, struct nouveau_bo *bo,
+                     uint32_t data, uint32_t flags, uint32_t vor, uint32_t tor)
+{
+       *push->cur++ = pushbuf_krel(push, bo, data, flags, vor, tor);
+}
+
+int
+nouveau_pushbuf_validate(struct nouveau_pushbuf *push)
+{
+       return pushbuf_validate(push, true);
+}
+
+uint32_t
+nouveau_pushbuf_refd(struct nouveau_pushbuf *push, struct nouveau_bo *bo)
+{
+       struct drm_nouveau_gem_pushbuf_bo *kref;
+       uint32_t flags = 0;
+
+       if (cli_push_get(push->client, bo) == push) {
+               kref = cli_kref_get(push->client, bo);
+               if (kref->read_domains)
+                       flags |= NOUVEAU_BO_RD;
+               if (kref->write_domains)
+                       flags |= NOUVEAU_BO_WR;
+       }
+
+       return flags;
+}
+
+int
+nouveau_pushbuf_kick(struct nouveau_pushbuf *push, struct nouveau_object *chan)
+{
+       if (!push->channel)
+               return pushbuf_submit(push, chan);
+       pushbuf_flush(push);
+       return pushbuf_validate(push, false);
+}
diff --git a/omap/Makefile.am b/omap/Makefile.am
new file mode 100644 (file)
index 0000000..c77520b
--- /dev/null
@@ -0,0 +1,22 @@
+AM_CFLAGS = \
+       $(WARN_CFLAGS) \
+       -I$(top_srcdir) \
+       -I$(top_srcdir)/omap \
+       $(PTHREADSTUBS_CFLAGS) \
+       -I$(top_srcdir)/include/drm
+
+libdrm_omap_la_LTLIBRARIES = libdrm_omap.la
+libdrm_omap_ladir = $(libdir)
+libdrm_omap_la_LDFLAGS = -version-number 1:0:0 -no-undefined
+libdrm_omap_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
+
+libdrm_omap_la_SOURCES = omap_drm.c
+
+libdrm_omapcommonincludedir = ${includedir}/omap
+libdrm_omapcommoninclude_HEADERS = omap_drm.h
+
+libdrm_omapincludedir = ${includedir}/libdrm
+libdrm_omapinclude_HEADERS = omap_drmif.h
+
+pkgconfigdir = @pkgconfigdir@
+pkgconfig_DATA = libdrm_omap.pc
diff --git a/omap/libdrm_omap.pc.in b/omap/libdrm_omap.pc.in
new file mode 100644 (file)
index 0000000..024533b
--- /dev/null
@@ -0,0 +1,11 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+includedir=@includedir@
+
+Name: libdrm_omap
+Description: Userspace interface to omap kernel DRM services
+Version: 0.6
+Libs: -L${libdir} -ldrm_omap
+Cflags: -I${includedir} -I${includedir}/libdrm -I${includedir}/omap
+Requires.private: libdrm
diff --git a/omap/omap_drm.c b/omap/omap_drm.c
new file mode 100644 (file)
index 0000000..336da11
--- /dev/null
@@ -0,0 +1,331 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright (C) 2011 Texas Instruments, Inc
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ *
+ * Authors:
+ *    Rob Clark <rob@ti.com>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <linux/stddef.h>
+#include <errno.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#include <xf86drm.h>
+
+#include "omap_drm.h"
+#include "omap_drmif.h"
+
+#define __round_mask(x, y) ((__typeof__(x))((y)-1))
+#define round_up(x, y) ((((x)-1) | __round_mask(x, y))+1)
+#define PAGE_SIZE 4096
+
+struct omap_device {
+       int fd;
+};
+
+/* a GEM buffer object allocated from the DRM device */
+struct omap_bo {
+       struct omap_device      *dev;
+       void            *map;           /* userspace mmap'ing (if there is one) */
+       uint32_t        size;
+       uint32_t        handle;
+       uint32_t        name;           /* flink global handle (DRI2 name) */
+       uint64_t        offset;         /* offset to mmap() */
+       int             fd;             /* dmabuf handle */
+};
+
+struct omap_device * omap_device_new(int fd)
+{
+       struct omap_device *dev = calloc(sizeof(*dev), 1);
+       if (!dev)
+               return NULL;
+       dev->fd = fd;
+       return dev;
+}
+
+void omap_device_del(struct omap_device *dev)
+{
+       free(dev);
+}
+
+int omap_get_param(struct omap_device *dev, uint64_t param, uint64_t *value)
+{
+       struct drm_omap_param req = {
+                       .param = param,
+       };
+       int ret;
+
+       ret = drmCommandWriteRead(dev->fd, DRM_OMAP_GET_PARAM, &req, sizeof(req));
+       if (ret) {
+               return ret;
+       }
+
+       *value = req.value;
+
+       return 0;
+}
+
+int omap_set_param(struct omap_device *dev, uint64_t param, uint64_t value)
+{
+       struct drm_omap_param req = {
+                       .param = param,
+                       .value = value,
+       };
+       return drmCommandWrite(dev->fd, DRM_OMAP_SET_PARAM, &req, sizeof(req));
+}
+
+/* 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 = NULL;
+       struct drm_omap_gem_new req = {
+                       .size = size,
+                       .flags = flags,
+       };
+
+       if (size.bytes == 0) {
+               goto fail;
+       }
+
+       bo = calloc(sizeof(*bo), 1);
+       if (!bo) {
+               goto fail;
+       }
+
+       bo->dev = dev;
+
+       if (flags & OMAP_BO_TILED) {
+               bo->size = round_up(size.tiled.width, PAGE_SIZE) * size.tiled.height;
+       } else {
+               bo->size = size.bytes;
+       }
+
+       if (drmCommandWriteRead(dev->fd, DRM_OMAP_GEM_NEW, &req, sizeof(req))) {
+               goto fail;
+       }
+
+       bo->handle = req.handle;
+
+       return bo;
+
+fail:
+       free(bo);
+       return NULL;
+}
+
+
+/* allocate a new (un-tiled) buffer object */
+struct omap_bo * omap_bo_new(struct omap_device *dev,
+               uint32_t size, uint32_t flags)
+{
+       union omap_gem_size gsize = {
+                       .bytes = size,
+       };
+       if (flags & OMAP_BO_TILED) {
+               return NULL;
+       }
+       return omap_bo_new_impl(dev, gsize, flags);
+}
+
+/* allocate a new buffer object */
+struct omap_bo * omap_bo_new_tiled(struct omap_device *dev,
+               uint32_t width, uint32_t height, uint32_t flags)
+{
+       union omap_gem_size gsize = {
+                       .tiled = {
+                               .width = width,
+                               .height = height,
+                       },
+       };
+       if (!(flags & OMAP_BO_TILED)) {
+               return NULL;
+       }
+       return omap_bo_new_impl(dev, gsize, flags);
+}
+
+/* get buffer info */
+static int get_buffer_info(struct omap_bo *bo)
+{
+       struct drm_omap_gem_info req = {
+                       .handle = bo->handle,
+       };
+       int ret = drmCommandWriteRead(bo->dev->fd, DRM_OMAP_GEM_INFO,
+                       &req, sizeof(req));
+       if (ret) {
+               return ret;
+       }
+
+       /* really all we need for now is mmap offset */
+       bo->offset = req.offset;
+       bo->size = req.size;
+
+       return 0;
+}
+
+/* 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 drm_gem_open req = {
+                       .name = name,
+       };
+
+       bo = calloc(sizeof(*bo), 1);
+       if (!bo) {
+               goto fail;
+       }
+
+       if (drmIoctl(dev->fd, DRM_IOCTL_GEM_OPEN, &req)) {
+               goto fail;
+       }
+
+       bo->dev = dev;
+       bo->name = name;
+       bo->handle = req.handle;
+
+       return bo;
+
+fail:
+       free(bo);
+       return NULL;
+}
+
+/* destroy a buffer object */
+void omap_bo_del(struct omap_bo *bo)
+{
+       if (!bo) {
+               return;
+       }
+
+       if (bo->map) {
+               munmap(bo->map, bo->size);
+       }
+
+       if (bo->handle) {
+               struct drm_gem_close req = {
+                               .handle = bo->handle,
+               };
+
+               drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_CLOSE, &req);
+       }
+
+       free(bo);
+}
+
+/* get the global flink/DRI2 buffer name */
+int omap_bo_get_name(struct omap_bo *bo, uint32_t *name)
+{
+       if (!bo->name) {
+               struct drm_gem_flink req = {
+                               .handle = bo->handle,
+               };
+               int ret;
+
+               ret = drmIoctl(bo->dev->fd, DRM_IOCTL_GEM_FLINK, &req);
+               if (ret) {
+                       return ret;
+               }
+
+               bo->name = req.name;
+       }
+
+       *name = bo->name;
+
+       return 0;
+}
+
+uint32_t omap_bo_handle(struct omap_bo *bo)
+{
+       return bo->handle;
+}
+
+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 bo->fd;
+}
+
+uint32_t omap_bo_size(struct omap_bo *bo)
+{
+       if (!bo->size) {
+               get_buffer_info(bo);
+       }
+       return bo->size;
+}
+
+void * omap_bo_map(struct omap_bo *bo)
+{
+       if (!bo->map) {
+               if (!bo->offset) {
+                       get_buffer_info(bo);
+               }
+
+               bo->map = mmap(0, bo->size, PROT_READ | PROT_WRITE,
+                               MAP_SHARED, bo->dev->fd, bo->offset);
+               if (bo->map == MAP_FAILED) {
+                       bo->map = NULL;
+               }
+       }
+       return bo->map;
+}
+
+int omap_bo_cpu_prep(struct omap_bo *bo, enum omap_gem_op op)
+{
+       struct drm_omap_gem_cpu_prep req = {
+                       .handle = bo->handle,
+                       .op = op,
+       };
+       return drmCommandWrite(bo->dev->fd,
+                       DRM_OMAP_GEM_CPU_PREP, &req, sizeof(req));
+}
+
+int omap_bo_cpu_fini(struct omap_bo *bo, enum omap_gem_op op)
+{
+       struct drm_omap_gem_cpu_fini req = {
+                       .handle = bo->handle,
+                       .op = op,
+                       .nregions = 0,
+       };
+       return drmCommandWrite(bo->dev->fd,
+                       DRM_OMAP_GEM_CPU_FINI, &req, sizeof(req));
+}
diff --git a/omap/omap_drm.h b/omap/omap_drm.h
new file mode 100644 (file)
index 0000000..f677cd8
--- /dev/null
@@ -0,0 +1,134 @@
+/* -*- mode: C; c-file-style: "k&r"; tab-width 4; indent-tabs-mode: t; -*- */
+
+/*
+ * Copyright (C) 2011 Texas Instruments, Inc
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ *
+ * Authors:
+ *    Rob Clark <rob@ti.com>
+ */
+
+#ifndef __OMAP_DRM_H__
+#define __OMAP_DRM_H__
+
+#include "drm.h"
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints.
+ */
+
+#define OMAP_PARAM_CHIPSET_ID  1       /* ie. 0x3430, 0x4430, etc */
+
+struct drm_omap_param {
+       uint64_t param;                 /* in */
+       uint64_t value;                 /* in (set_param), out (get_param) */
+};
+
+struct drm_omap_get_base {
+       char plugin_name[64];           /* in */
+       uint32_t ioctl_base;            /* out */
+       uint32_t __pad;
+};
+
+#define OMAP_BO_SCANOUT                0x00000001      /* scanout capable (phys contiguous) */
+#define OMAP_BO_CACHE_MASK     0x00000006      /* cache type mask, see cache modes */
+#define OMAP_BO_TILED_MASK     0x00000f00      /* tiled mapping mask, see tiled modes */
+
+/* cache modes */
+#define OMAP_BO_CACHED         0x00000000      /* default */
+#define OMAP_BO_WC             0x00000002      /* write-combine */
+#define OMAP_BO_UNCACHED       0x00000004      /* strongly-ordered (uncached) */
+
+/* tiled modes */
+#define OMAP_BO_TILED_8                0x00000100
+#define OMAP_BO_TILED_16       0x00000200
+#define OMAP_BO_TILED_32       0x00000300
+#define OMAP_BO_TILED          (OMAP_BO_TILED_8 | OMAP_BO_TILED_16 | OMAP_BO_TILED_32)
+
+union omap_gem_size {
+       uint32_t bytes;         /* (for non-tiled formats) */
+       struct {
+               uint16_t width;
+               uint16_t height;
+       } tiled;                /* (for tiled formats) */
+};
+
+struct drm_omap_gem_new {
+       union omap_gem_size size;       /* in */
+       uint32_t flags;                 /* in */
+       uint32_t handle;                /* out */
+       uint32_t __pad;
+};
+
+/* mask of operations: */
+enum omap_gem_op {
+       OMAP_GEM_READ = 0x01,
+       OMAP_GEM_WRITE = 0x02,
+};
+
+struct drm_omap_gem_cpu_prep {
+       uint32_t handle;                /* buffer handle (in) */
+       uint32_t op;                    /* mask of omap_gem_op (in) */
+};
+
+struct drm_omap_gem_cpu_fini {
+       uint32_t handle;                /* buffer handle (in) */
+       uint32_t op;                    /* mask of omap_gem_op (in) */
+       /* TODO maybe here we pass down info about what regions are touched
+        * by sw so we can be clever about cache ops?  For now a placeholder,
+        * set to zero and we just do full buffer flush..
+        */
+       uint32_t nregions;
+       uint32_t __pad;
+};
+
+struct drm_omap_gem_info {
+       uint32_t handle;                /* buffer handle (in) */
+       uint32_t pad;
+       uint64_t offset;                /* mmap offset (out) */
+       /* note: in case of tiled buffers, the user virtual size can be
+        * different from the physical size (ie. how many pages are needed
+        * to back the object) which is returned in DRM_IOCTL_GEM_OPEN..
+        * This size here is the one that should be used if you want to
+        * mmap() the buffer:
+        */
+       uint32_t size;                  /* virtual size for mmap'ing (out) */
+       uint32_t __pad;
+};
+
+#define DRM_OMAP_GET_PARAM             0x00
+#define DRM_OMAP_SET_PARAM             0x01
+#define DRM_OMAP_GET_BASE              0x02
+#define DRM_OMAP_GEM_NEW               0x03
+#define DRM_OMAP_GEM_CPU_PREP          0x04
+#define DRM_OMAP_GEM_CPU_FINI          0x05
+#define DRM_OMAP_GEM_INFO              0x06
+#define DRM_OMAP_NUM_IOCTLS            0x07
+
+#define DRM_IOCTL_OMAP_GET_PARAM       DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_PARAM, struct drm_omap_param)
+#define DRM_IOCTL_OMAP_SET_PARAM       DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_SET_PARAM, struct drm_omap_param)
+#define DRM_IOCTL_OMAP_GET_BASE                DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GET_BASE, struct drm_omap_get_base)
+#define DRM_IOCTL_OMAP_GEM_NEW         DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_NEW, struct drm_omap_gem_new)
+#define DRM_IOCTL_OMAP_GEM_CPU_PREP    DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_PREP, struct drm_omap_gem_cpu_prep)
+#define DRM_IOCTL_OMAP_GEM_CPU_FINI    DRM_IOW (DRM_COMMAND_BASE + DRM_OMAP_GEM_CPU_FINI, struct drm_omap_gem_cpu_fini)
+#define DRM_IOCTL_OMAP_GEM_INFO                DRM_IOWR(DRM_COMMAND_BASE + DRM_OMAP_GEM_INFO, struct drm_omap_gem_info)
+
+#endif /* __OMAP_DRM_H__ */
diff --git a/omap/omap_drmif.h b/omap/omap_drmif.h
new file mode 100644 (file)
index 0000000..1e03eee
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2011 Texas Instruments, Inc
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ *
+ * Authors:
+ *    Rob Clark <rob@ti.com>
+ */
+
+#ifndef OMAP_DRMIF_H_
+#define OMAP_DRMIF_H_
+
+#include <xf86drm.h>
+#include <stdint.h>
+#include <omap_drm.h>
+
+struct omap_bo;
+struct omap_device;
+
+/* device related functions:
+ */
+
+struct omap_device * omap_device_new(int fd);
+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);
+
+/* buffer-object related functions:
+ */
+
+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_from_name(struct omap_device *dev, uint32_t name);
+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);
+int omap_bo_cpu_fini(struct omap_bo *bo, enum omap_gem_op op);
+
+#endif /* OMAP_DRMIF_H_ */
index d9ed836..939da25 100644 (file)
@@ -1,7 +1,7 @@
 #sbs-git:slp/pkgs/xorg/lib/libdrm libdrm 2.4.27 4df9ab272d6eac089f89ecd9302d39263541a794
 Name:           libdrm
-Version:        2.4.27
-Release:        4
+Version:        2.4.35
+Release:        1
 License:        MIT
 Summary:        Userspace interface to kernel DRM services
 Group:          System/Libraries
@@ -9,7 +9,6 @@ Source0:        %{name}-%{version}.tar.gz
 BuildRequires:  kernel-headers
 BuildRequires:  pkgconfig(xorg-macros)
 BuildRequires:  pkgconfig(pthread-stubs)
-BuildRequires:  pkgconfig(pciaccess)
 
 %description
 Description: %{summary}
@@ -52,8 +51,8 @@ Userspace interface to kernel DRM buffer management
 
 %build
 %reconfigure --prefix=%{_prefix} --mandir=%{_prefix}/share/man --infodir=%{_prefix}/share/info \
-             --enable-static=yes --enable-udev --enable-libkms \
-             --disable-nouveau-experimental-api --disable-radeon --disable-intel
+             --enable-static=yes --enable-udev --enable-libkms --enable-exynos-experimental-api \
+             --disable-nouveau --disable-radeon --disable-intel
 
 make %{?_smp_mflags}
 
@@ -77,13 +76,16 @@ make %{?_smp_mflags}
 %files devel
 %dir %{_includedir}/libdrm
 %{_includedir}/*
+%{_includedir}/exynos/*
 %{_libdir}/libdrm.so
 %{_libdir}/libdrm_slp.so
+%{_libdir}/libdrm_exynos.so
 %{_libdir}/libkms.so
 %{_libdir}/pkgconfig/*
 
 %files -n libdrm2
 %{_libdir}/libdrm.so.*
+%{_libdir}/libdrm_exynos.so.*
 
 %files slp1
 %{_libdir}/libdrm_slp*.so.*
index dc94b5f..37be8cc 100644 (file)
@@ -40,6 +40,7 @@ libdrm_radeon_la_SOURCES = \
        radeon_cs_space.c \
        radeon_bo.c \
        radeon_cs.c \
+       radeon_surface.c \
        bof.c \
        bof.h
 
@@ -47,10 +48,12 @@ libdrm_radeonincludedir = ${includedir}/libdrm
 libdrm_radeoninclude_HEADERS = \
        radeon_bo.h \
        radeon_cs.h \
+       radeon_surface.h \
        radeon_bo_gem.h \
        radeon_cs_gem.h \
        radeon_bo_int.h \
-       radeon_cs_int.h
+       radeon_cs_int.h \
+       r600_pci_ids.h
 
 pkgconfigdir = @pkgconfigdir@
 pkgconfig_DATA = libdrm_radeon.pc
diff --git a/radeon/r600_pci_ids.h b/radeon/r600_pci_ids.h
new file mode 100644 (file)
index 0000000..989ec00
--- /dev/null
@@ -0,0 +1,353 @@
+CHIPSET(0x9400, R600_9400, R600)
+CHIPSET(0x9401, R600_9401, R600)
+CHIPSET(0x9402, R600_9402, R600)
+CHIPSET(0x9403, R600_9403, R600)
+CHIPSET(0x9405, R600_9405, R600)
+CHIPSET(0x940A, R600_940A, R600)
+CHIPSET(0x940B, R600_940B, R600)
+CHIPSET(0x940F, R600_940F, R600)
+
+CHIPSET(0x94C0, RV610_94C0, RV610)
+CHIPSET(0x94C1, RV610_94C1, RV610)
+CHIPSET(0x94C3, RV610_94C3, RV610)
+CHIPSET(0x94C4, RV610_94C4, RV610)
+CHIPSET(0x94C5, RV610_94C5, RV610)
+CHIPSET(0x94C6, RV610_94C6, RV610)
+CHIPSET(0x94C7, RV610_94C7, RV610)
+CHIPSET(0x94C8, RV610_94C8, RV610)
+CHIPSET(0x94C9, RV610_94C9, RV610)
+CHIPSET(0x94CB, RV610_94CB, RV610)
+CHIPSET(0x94CC, RV610_94CC, RV610)
+CHIPSET(0x94CD, RV610_94CD, RV610)
+
+CHIPSET(0x9580, RV630_9580, RV630)
+CHIPSET(0x9581, RV630_9581, RV630)
+CHIPSET(0x9583, RV630_9583, RV630)
+CHIPSET(0x9586, RV630_9586, RV630)
+CHIPSET(0x9587, RV630_9587, RV630)
+CHIPSET(0x9588, RV630_9588, RV630)
+CHIPSET(0x9589, RV630_9589, RV630)
+CHIPSET(0x958A, RV630_958A, RV630)
+CHIPSET(0x958B, RV630_958B, RV630)
+CHIPSET(0x958C, RV630_958C, RV630)
+CHIPSET(0x958D, RV630_958D, RV630)
+CHIPSET(0x958E, RV630_958E, RV630)
+CHIPSET(0x958F, RV630_958F, RV630)
+
+CHIPSET(0x9500, RV670_9500, RV670)
+CHIPSET(0x9501, RV670_9501, RV670)
+CHIPSET(0x9504, RV670_9504, RV670)
+CHIPSET(0x9505, RV670_9505, RV670)
+CHIPSET(0x9506, RV670_9506, RV670)
+CHIPSET(0x9507, RV670_9507, RV670)
+CHIPSET(0x9508, RV670_9508, RV670)
+CHIPSET(0x9509, RV670_9509, RV670)
+CHIPSET(0x950F, RV670_950F, RV670)
+CHIPSET(0x9511, RV670_9511, RV670)
+CHIPSET(0x9515, RV670_9515, RV670)
+CHIPSET(0x9517, RV670_9517, RV670)
+CHIPSET(0x9519, RV670_9519, RV670)
+
+CHIPSET(0x95C0, RV620_95C0, RV620)
+CHIPSET(0x95C2, RV620_95C2, RV620)
+CHIPSET(0x95C4, RV620_95C4, RV620)
+CHIPSET(0x95C5, RV620_95C5, RV620)
+CHIPSET(0x95C6, RV620_95C6, RV620)
+CHIPSET(0x95C7, RV620_95C7, RV620)
+CHIPSET(0x95C9, RV620_95C9, RV620)
+CHIPSET(0x95CC, RV620_95CC, RV620)
+CHIPSET(0x95CD, RV620_95CD, RV620)
+CHIPSET(0x95CE, RV620_95CE, RV620)
+CHIPSET(0x95CF, RV620_95CF, RV620)
+
+CHIPSET(0x9590, RV635_9590, RV635)
+CHIPSET(0x9591, RV635_9591, RV635)
+CHIPSET(0x9593, RV635_9593, RV635)
+CHIPSET(0x9595, RV635_9595, RV635)
+CHIPSET(0x9596, RV635_9596, RV635)
+CHIPSET(0x9597, RV635_9597, RV635)
+CHIPSET(0x9598, RV635_9598, RV635)
+CHIPSET(0x9599, RV635_9599, RV635)
+CHIPSET(0x959B, RV635_959B, RV635)
+
+CHIPSET(0x9610, RS780_9610, RS780)
+CHIPSET(0x9611, RS780_9611, RS780)
+CHIPSET(0x9612, RS780_9612, RS780)
+CHIPSET(0x9613, RS780_9613, RS780)
+CHIPSET(0x9614, RS780_9614, RS780)
+CHIPSET(0x9615, RS780_9615, RS780)
+CHIPSET(0x9616, RS780_9616, RS780)
+
+CHIPSET(0x9710, RS880_9710, RS880)
+CHIPSET(0x9711, RS880_9711, RS880)
+CHIPSET(0x9712, RS880_9712, RS880)
+CHIPSET(0x9713, RS880_9713, RS880)
+CHIPSET(0x9714, RS880_9714, RS880)
+CHIPSET(0x9715, RS880_9715, RS880)
+
+CHIPSET(0x9440, RV770_9440, RV770)
+CHIPSET(0x9441, RV770_9441, RV770)
+CHIPSET(0x9442, RV770_9442, RV770)
+CHIPSET(0x9443, RV770_9443, RV770)
+CHIPSET(0x9444, RV770_9444, RV770)
+CHIPSET(0x9446, RV770_9446, RV770)
+CHIPSET(0x944A, RV770_944A, RV770)
+CHIPSET(0x944B, RV770_944B, RV770)
+CHIPSET(0x944C, RV770_944C, RV770)
+CHIPSET(0x944E, RV770_944E, RV770)
+CHIPSET(0x9450, RV770_9450, RV770)
+CHIPSET(0x9452, RV770_9452, RV770)
+CHIPSET(0x9456, RV770_9456, RV770)
+CHIPSET(0x945A, RV770_945A, RV770)
+CHIPSET(0x945B, RV770_945B, RV770)
+CHIPSET(0x945E, RV770_945E, RV770)
+CHIPSET(0x9460, RV790_9460, RV770)
+CHIPSET(0x9462, RV790_9462, RV770)
+CHIPSET(0x946A, RV770_946A, RV770)
+CHIPSET(0x946B, RV770_946B, RV770)
+CHIPSET(0x947A, RV770_947A, RV770)
+CHIPSET(0x947B, RV770_947B, RV770)
+
+CHIPSET(0x9480, RV730_9480, RV730)
+CHIPSET(0x9487, RV730_9487, RV730)
+CHIPSET(0x9488, RV730_9488, RV730)
+CHIPSET(0x9489, RV730_9489, RV730)
+CHIPSET(0x948A, RV730_948A, RV730)
+CHIPSET(0x948F, RV730_948F, RV730)
+CHIPSET(0x9490, RV730_9490, RV730)
+CHIPSET(0x9491, RV730_9491, RV730)
+CHIPSET(0x9495, RV730_9495, RV730)
+CHIPSET(0x9498, RV730_9498, RV730)
+CHIPSET(0x949C, RV730_949C, RV730)
+CHIPSET(0x949E, RV730_949E, RV730)
+CHIPSET(0x949F, RV730_949F, RV730)
+
+CHIPSET(0x9540, RV710_9540, RV710)
+CHIPSET(0x9541, RV710_9541, RV710)
+CHIPSET(0x9542, RV710_9542, RV710)
+CHIPSET(0x954E, RV710_954E, RV710)
+CHIPSET(0x954F, RV710_954F, RV710)
+CHIPSET(0x9552, RV710_9552, RV710)
+CHIPSET(0x9553, RV710_9553, RV710)
+CHIPSET(0x9555, RV710_9555, RV710)
+CHIPSET(0x9557, RV710_9557, RV710)
+CHIPSET(0x955F, RV710_955F, RV710)
+
+CHIPSET(0x94A0, RV740_94A0, RV740)
+CHIPSET(0x94A1, RV740_94A1, RV740)
+CHIPSET(0x94A3, RV740_94A3, RV740)
+CHIPSET(0x94B1, RV740_94B1, RV740)
+CHIPSET(0x94B3, RV740_94B3, RV740)
+CHIPSET(0x94B4, RV740_94B4, RV740)
+CHIPSET(0x94B5, RV740_94B5, RV740)
+CHIPSET(0x94B9, RV740_94B9, RV740)
+
+CHIPSET(0x68E0, CEDAR_68E0, CEDAR)
+CHIPSET(0x68E1, CEDAR_68E1, CEDAR)
+CHIPSET(0x68E4, CEDAR_68E4, CEDAR)
+CHIPSET(0x68E5, CEDAR_68E5, CEDAR)
+CHIPSET(0x68E8, CEDAR_68E8, CEDAR)
+CHIPSET(0x68E9, CEDAR_68E9, CEDAR)
+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(0x68C8, REDWOOD_68C8, REDWOOD)
+CHIPSET(0x68C9, REDWOOD_68C9, REDWOOD)
+CHIPSET(0x68D8, REDWOOD_68D8, REDWOOD)
+CHIPSET(0x68D9, REDWOOD_68D9, REDWOOD)
+CHIPSET(0x68DA, REDWOOD_68DA, REDWOOD)
+CHIPSET(0x68DE, REDWOOD_68DE, REDWOOD)
+
+CHIPSET(0x68A0, JUNIPER_68A0, JUNIPER)
+CHIPSET(0x68A1, JUNIPER_68A1, JUNIPER)
+CHIPSET(0x68A8, JUNIPER_68A8, JUNIPER)
+CHIPSET(0x68A9, JUNIPER_68A9, JUNIPER)
+CHIPSET(0x68B0, JUNIPER_68B0, JUNIPER)
+CHIPSET(0x68B8, JUNIPER_68B8, JUNIPER)
+CHIPSET(0x68B9, JUNIPER_68B9, JUNIPER)
+CHIPSET(0x68BA, JUNIPER_68BA, JUNIPER)
+CHIPSET(0x68BE, JUNIPER_68BE, JUNIPER)
+CHIPSET(0x68BF, JUNIPER_68BF, JUNIPER)
+
+CHIPSET(0x6880, CYPRESS_6880, CYPRESS)
+CHIPSET(0x6888, CYPRESS_6888, CYPRESS)
+CHIPSET(0x6889, CYPRESS_6889, CYPRESS)
+CHIPSET(0x688A, CYPRESS_688A, CYPRESS)
+CHIPSET(0x6898, CYPRESS_6898, CYPRESS)
+CHIPSET(0x6899, CYPRESS_6899, CYPRESS)
+CHIPSET(0x689B, CYPRESS_689B, CYPRESS)
+CHIPSET(0x689E, CYPRESS_689E, CYPRESS)
+
+CHIPSET(0x689C, HEMLOCK_689C, HEMLOCK)
+CHIPSET(0x689D, HEMLOCK_689D, HEMLOCK)
+
+CHIPSET(0x9802, PALM_9802, PALM)
+CHIPSET(0x9803, PALM_9803, PALM)
+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)
+CHIPSET(0x9642, SUMO2_9642, SUMO2)
+CHIPSET(0x9643, SUMO2_9643, SUMO2)
+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)
+
+CHIPSET(0x6700, CAYMAN_6700, CAYMAN)
+CHIPSET(0x6701, CAYMAN_6701, CAYMAN)
+CHIPSET(0x6702, CAYMAN_6702, CAYMAN)
+CHIPSET(0x6703, CAYMAN_6703, CAYMAN)
+CHIPSET(0x6704, CAYMAN_6704, CAYMAN)
+CHIPSET(0x6705, CAYMAN_6705, CAYMAN)
+CHIPSET(0x6706, CAYMAN_6706, CAYMAN)
+CHIPSET(0x6707, CAYMAN_6707, CAYMAN)
+CHIPSET(0x6708, CAYMAN_6708, CAYMAN)
+CHIPSET(0x6709, CAYMAN_6709, CAYMAN)
+CHIPSET(0x6718, CAYMAN_6718, CAYMAN)
+CHIPSET(0x6719, CAYMAN_6719, CAYMAN)
+CHIPSET(0x671C, CAYMAN_671C, CAYMAN)
+CHIPSET(0x671D, CAYMAN_671D, CAYMAN)
+CHIPSET(0x671F, CAYMAN_671F, CAYMAN)
+
+CHIPSET(0x6720, BARTS_6720, BARTS)
+CHIPSET(0x6721, BARTS_6721, BARTS)
+CHIPSET(0x6722, BARTS_6722, BARTS)
+CHIPSET(0x6723, BARTS_6723, BARTS)
+CHIPSET(0x6724, BARTS_6724, BARTS)
+CHIPSET(0x6725, BARTS_6725, BARTS)
+CHIPSET(0x6726, BARTS_6726, BARTS)
+CHIPSET(0x6727, BARTS_6727, BARTS)
+CHIPSET(0x6728, BARTS_6728, BARTS)
+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)
+CHIPSET(0x6743, TURKS_6743, TURKS)
+CHIPSET(0x6744, TURKS_6744, TURKS)
+CHIPSET(0x6745, TURKS_6745, TURKS)
+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)
+CHIPSET(0x6842, TURKS_6842, TURKS)
+CHIPSET(0x6843, TURKS_6843, TURKS)
+CHIPSET(0x6849, TURKS_6849, TURKS)
+CHIPSET(0x6850, TURKS_6850, TURKS)
+CHIPSET(0x6858, TURKS_6858, TURKS)
+CHIPSET(0x6859, TURKS_6859, TURKS)
+
+CHIPSET(0x6760, CAICOS_6760, CAICOS)
+CHIPSET(0x6761, CAICOS_6761, CAICOS)
+CHIPSET(0x6762, CAICOS_6762, CAICOS)
+CHIPSET(0x6763, CAICOS_6763, CAICOS)
+CHIPSET(0x6764, CAICOS_6764, CAICOS)
+CHIPSET(0x6765, CAICOS_6765, CAICOS)
+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(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(0x6808, PITCAIRN_6808, PITCAIRN)
+CHIPSET(0x6809, PITCAIRN_6809, PITCAIRN)
+CHIPSET(0x6810, PITCAIRN_6810, 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)
index 208e1bb..be047a7 100644 (file)
@@ -65,13 +65,16 @@ static inline int radeon_cs_setup_bo(struct radeon_cs_space_check *sc, struct ra
     }
 
     if (bo->space_accounted == 0) {
-        if (write_domain == RADEON_GEM_DOMAIN_VRAM)
-            sizes->op_vram_write += bo->size;
-        else if (write_domain == RADEON_GEM_DOMAIN_GTT)
-            sizes->op_gart_write += bo->size;
-        else
+        if (write_domain) {
+            if (write_domain == RADEON_GEM_DOMAIN_VRAM)
+                sizes->op_vram_write += bo->size;
+            else if (write_domain == RADEON_GEM_DOMAIN_GTT)
+                sizes->op_gart_write += bo->size;
+            sc->new_accounted = write_domain;
+        } else {
             sizes->op_read += bo->size;
-        sc->new_accounted = (read_domains << 16) | write_domain;
+            sc->new_accounted = read_domains << 16;
+        }
     } else {
         uint16_t old_read, old_write;
 
diff --git a/radeon/radeon_surface.c b/radeon/radeon_surface.c
new file mode 100644 (file)
index 0000000..adf209d
--- /dev/null
@@ -0,0 +1,1025 @@
+/*
+ * Copyright Â© 2011 Red Hat All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ *      Jérôme Glisse <jglisse@redhat.com>
+ */
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include "drm.h"
+#include "xf86drm.h"
+#include "radeon_drm.h"
+#include "radeon_surface.h"
+
+#define ALIGN(value, alignment) (((value) + alignment - 1) & ~(alignment - 1))
+#define MAX2(A, B)              ((A) > (B) ? (A) : (B))
+#define MIN2(A, B)              ((A) < (B) ? (A) : (B))
+
+/* keep this private */
+enum radeon_family {
+    CHIP_UNKNOWN,
+    CHIP_R600,
+    CHIP_RV610,
+    CHIP_RV630,
+    CHIP_RV670,
+    CHIP_RV620,
+    CHIP_RV635,
+    CHIP_RS780,
+    CHIP_RS880,
+    CHIP_RV770,
+    CHIP_RV730,
+    CHIP_RV710,
+    CHIP_RV740,
+    CHIP_CEDAR,
+    CHIP_REDWOOD,
+    CHIP_JUNIPER,
+    CHIP_CYPRESS,
+    CHIP_HEMLOCK,
+    CHIP_PALM,
+    CHIP_SUMO,
+    CHIP_SUMO2,
+    CHIP_BARTS,
+    CHIP_TURKS,
+    CHIP_CAICOS,
+    CHIP_CAYMAN,
+    CHIP_ARUBA,
+    CHIP_TAHITI,
+    CHIP_PITCAIRN,
+    CHIP_VERDE,
+    CHIP_LAST,
+};
+
+typedef int (*hw_init_surface_t)(struct radeon_surface_manager *surf_man,
+                                 struct radeon_surface *surf);
+typedef int (*hw_best_surface_t)(struct radeon_surface_manager *surf_man,
+                                 struct radeon_surface *surf);
+
+struct radeon_hw_info {
+    /* apply to r6, eg */
+    uint32_t                    group_bytes;
+    uint32_t                    num_banks;
+    uint32_t                    num_pipes;
+    /* apply to eg */
+    uint32_t                    row_size;
+    unsigned                    allow_2d;
+};
+
+struct radeon_surface_manager {
+    int                         fd;
+    uint32_t                    device_id;
+    struct radeon_hw_info       hw_info;
+    unsigned                    family;
+    hw_init_surface_t           surface_init;
+    hw_best_surface_t           surface_best;
+};
+
+/* helper */
+static int radeon_get_value(int fd, unsigned req, uint32_t *value)
+{
+    struct drm_radeon_info info = {};
+    int r;
+
+    *value = 0;
+    info.request = req;
+    info.value = (uintptr_t)value;
+    r = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info,
+                            sizeof(struct drm_radeon_info));
+    return r;
+}
+
+static int radeon_get_family(struct radeon_surface_manager *surf_man)
+{
+    switch (surf_man->device_id) {
+#define CHIPSET(pci_id, name, fam) case pci_id: surf_man->family = CHIP_##fam; break;
+#include "r600_pci_ids.h"
+#undef CHIPSET
+    default:
+        return -EINVAL;
+    }
+    return 0;
+}
+
+static unsigned next_power_of_two(unsigned x)
+{
+   if (x <= 1)
+       return 1;
+
+   return (1 << ((sizeof(unsigned) * 8) - __builtin_clz(x - 1)));
+}
+
+static unsigned mip_minify(unsigned size, unsigned level)
+{
+    unsigned val;
+
+    val = MAX2(1, size >> level);
+    if (level > 0)
+        val = next_power_of_two(val);
+    return val;
+}
+
+static void surf_minify(struct radeon_surface *surf,
+                        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;
+            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);
+
+    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;
+
+    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+}
+
+/* ===========================================================================
+ * r600/r700 family
+ */
+static int r6_init_hw_info(struct radeon_surface_manager *surf_man)
+{
+    uint32_t tiling_config;
+    drmVersionPtr version;
+    int r;
+
+    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
+                         &tiling_config);
+    if (r) {
+        return r;
+    }
+
+    surf_man->hw_info.allow_2d = 0;
+    version = drmGetVersion(surf_man->fd);
+    if (version && version->version_minor >= 14) {
+        surf_man->hw_info.allow_2d = 1;
+    }
+
+    switch ((tiling_config & 0xe) >> 1) {
+    case 0:
+        surf_man->hw_info.num_pipes = 1;
+        break;
+    case 1:
+        surf_man->hw_info.num_pipes = 2;
+        break;
+    case 2:
+        surf_man->hw_info.num_pipes = 4;
+        break;
+    case 3:
+        surf_man->hw_info.num_pipes = 8;
+        break;
+    default:
+        surf_man->hw_info.num_pipes = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0x30) >> 4) {
+    case 0:
+        surf_man->hw_info.num_banks = 4;
+        break;
+    case 1:
+        surf_man->hw_info.num_banks = 8;
+        break;
+    default:
+        surf_man->hw_info.num_banks = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0xc0) >> 6) {
+    case 0:
+        surf_man->hw_info.group_bytes = 256;
+        break;
+    case 1:
+        surf_man->hw_info.group_bytes = 512;
+        break;
+    default:
+        surf_man->hw_info.group_bytes = 256;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+    return 0;
+}
+
+static int r6_surface_init_linear(struct radeon_surface_manager *surf_man,
+                                  struct radeon_surface *surf,
+                                  uint64_t offset, unsigned start_level)
+{
+    uint32_t xalign, yalign, zalign;
+    unsigned i;
+
+    /* compute alignment */
+    if (!start_level) {
+        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+    }
+    /* the 32 alignment is for scanout, cb or db but to allow texture to be
+     * easily bound as such we force this alignment to all surface
+     */
+    xalign = MAX2(1, surf_man->hw_info.group_bytes / surf->bpe);
+    yalign = 1;
+    zalign = 1;
+    if (surf->flags & RADEON_SURF_SCANOUT) {
+        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
+    }
+
+    /* 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);
+        /* 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 r6_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;
+    unsigned i;
+
+    /* compute alignment */
+    if (!start_level) {
+        surf->bo_alignment = MAX2(256, surf_man->hw_info.group_bytes);
+    }
+    xalign = MAX2(64, surf_man->hw_info.group_bytes / surf->bpe);
+    yalign = 1;
+    zalign = 1;
+
+    /* 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);
+        /* 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 r6_surface_init_1d(struct radeon_surface_manager *surf_man,
+                              struct radeon_surface *surf,
+                              uint64_t offset, unsigned start_level)
+{
+    uint32_t xalign, yalign, zalign, tilew;
+    unsigned i;
+
+    /* compute alignment */
+    tilew = 8;
+    xalign = surf_man->hw_info.group_bytes / (tilew * surf->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);
+    }
+    if (!start_level) {
+        surf->bo_alignment = MAX2(256, 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_1D;
+        surf_minify(surf, 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);
+        }
+    }
+    return 0;
+}
+
+static int r6_surface_init_2d(struct radeon_surface_manager *surf_man,
+                              struct radeon_surface *surf,
+                              uint64_t offset, unsigned start_level)
+{
+    uint32_t xalign, yalign, zalign, tilew;
+    unsigned i;
+
+    /* compute alignment */
+    tilew = 8;
+    zalign = 1;
+    xalign = (surf_man->hw_info.group_bytes * surf_man->hw_info.num_banks) /
+             (tilew * surf->bpe * surf->nsamples);
+    xalign = MAX2(tilew * surf_man->hw_info.num_banks, xalign);
+    yalign = tilew * surf_man->hw_info.num_pipes;
+    if (surf->flags & RADEON_SURF_SCANOUT) {
+        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
+    }
+    if (!start_level) {
+        surf->bo_alignment =
+            MAX2(surf_man->hw_info.num_pipes *
+                 surf_man->hw_info.num_banks *
+                 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);
+        if (surf->level[i].mode == RADEON_SURF_MODE_1D) {
+            return r6_surface_init_1d(surf_man, surf, offset, i);
+        }
+        /* 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 r6_surface_init(struct radeon_surface_manager *surf_man,
+                           struct radeon_surface *surf)
+{
+    unsigned mode;
+    int r;
+
+    /* tiling mode */
+    mode = (surf->flags >> RADEON_SURF_MODE_SHIFT) & RADEON_SURF_MODE_MASK;
+
+    /* force 1d on kernel that can't do 2d */
+    if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
+        mode = RADEON_SURF_MODE_1D;
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(mode, MODE);
+    }
+
+    /* check surface dimension */
+    if (surf->npix_x > 8192 || surf->npix_y > 8192 || surf->npix_z > 8192) {
+        return -EINVAL;
+    }
+
+    /* check mipmap last_level */
+    if (surf->last_level > 14) {
+        return -EINVAL;
+    }
+
+    /* 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 = r6_surface_init_linear_aligned(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_1D:
+        r = r6_surface_init_1d(surf_man, surf, 0, 0);
+        break;
+    case RADEON_SURF_MODE_2D:
+        r = r6_surface_init_2d(surf_man, surf, 0, 0);
+        break;
+    default:
+        return -EINVAL;
+    }
+    return r;
+}
+
+static int r6_surface_best(struct radeon_surface_manager *surf_man,
+                           struct radeon_surface *surf)
+{
+    /* no value to optimize for r6xx/r7xx */
+    return 0;
+}
+
+
+/* ===========================================================================
+ * evergreen family
+ */
+static int eg_init_hw_info(struct radeon_surface_manager *surf_man)
+{
+    uint32_t tiling_config;
+    drmVersionPtr version;
+    int r;
+
+    r = radeon_get_value(surf_man->fd, RADEON_INFO_TILING_CONFIG,
+                         &tiling_config);
+    if (r) {
+        return r;
+    }
+
+    surf_man->hw_info.allow_2d = 0;
+    version = drmGetVersion(surf_man->fd);
+    if (version && version->version_minor >= 14) {
+        surf_man->hw_info.allow_2d = 1;
+    }
+
+    switch (tiling_config & 0xf) {
+    case 0:
+        surf_man->hw_info.num_pipes = 1;
+        break;
+    case 1:
+        surf_man->hw_info.num_pipes = 2;
+        break;
+    case 2:
+        surf_man->hw_info.num_pipes = 4;
+        break;
+    case 3:
+        surf_man->hw_info.num_pipes = 8;
+        break;
+    default:
+        surf_man->hw_info.num_pipes = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0xf0) >> 4) {
+    case 0:
+        surf_man->hw_info.num_banks = 4;
+        break;
+    case 1:
+        surf_man->hw_info.num_banks = 8;
+        break;
+    case 2:
+        surf_man->hw_info.num_banks = 16;
+        break;
+    default:
+        surf_man->hw_info.num_banks = 8;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0xf00) >> 8) {
+    case 0:
+        surf_man->hw_info.group_bytes = 256;
+        break;
+    case 1:
+        surf_man->hw_info.group_bytes = 512;
+        break;
+    default:
+        surf_man->hw_info.group_bytes = 256;
+        surf_man->hw_info.allow_2d = 0;
+        break;
+    }
+
+    switch ((tiling_config & 0xf000) >> 12) {
+    case 0:
+        surf_man->hw_info.row_size = 1024;
+        break;
+    case 1:
+        surf_man->hw_info.row_size = 2048;
+        break;
+    case 2:
+        surf_man->hw_info.row_size = 4096;
+        break;
+    default:
+        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,
+                           unsigned level,
+                           unsigned slice_pt,
+                           unsigned mtilew,
+                           unsigned mtileh,
+                           unsigned mtileb,
+                           unsigned offset)
+{
+    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;
+            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);
+
+    /* macro tile per row */
+    mtile_pr = surf->level[level].nblk_x / mtilew;
+    /* macro tile per slice */
+    mtile_ps = (mtile_pr * surf->level[level].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;
+
+    surf->bo_size = offset + surf->level[level].slice_size * surf->level[level].nblk_z * surf->array_size;
+}
+
+static int eg_surface_init_1d(struct radeon_surface_manager *surf_man,
+                              struct radeon_surface *surf,
+                              uint64_t offset, unsigned start_level)
+{
+    uint32_t xalign, yalign, zalign, tilew;
+    unsigned i;
+
+    /* 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 = MAX2(tilew, xalign);
+    yalign = tilew;
+    zalign = 1;
+    if (surf->flags & RADEON_SURF_SCANOUT) {
+        xalign = MAX2((surf->bpe == 1) ? 64 : 32, xalign);
+    }
+    if (!start_level) {
+        surf->bo_alignment = MAX2(256, 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_1D;
+        surf_minify(surf, 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,
+                              uint64_t offset, unsigned start_level)
+{
+    unsigned tilew, tileh, tileb;
+    unsigned mtilew, mtileh, mtileb;
+    unsigned slice_pt;
+    unsigned i;
+
+    surf->stencil_offset = 0;
+    /* compute tile values */
+    tilew = 8;
+    tileh = 8;
+    tileb = tilew * tileh * surf->bpe * surf->nsamples;
+    /* slices per tile */
+    slice_pt = 1;
+    if (tileb > surf->tile_split) {
+        slice_pt = tileb / surf->tile_split;
+    }
+    tileb = tileb / slice_pt;
+
+    /* macro tile width & height */
+    mtilew = (tilew * surf->bankw * surf_man->hw_info.num_pipes) * surf->mtilea;
+    mtileh = (tileh * surf->bankh * surf_man->hw_info.num_banks) / surf->mtilea;
+    /* macro tile bytes */
+    mtileb = (mtilew / tilew) * (mtileh / tileh) * tileb;
+
+    if (!start_level) {
+        surf->bo_alignment = MAX2(256, mtileb);
+    }
+
+    /* 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);
+        }
+        /* 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_sanity(struct radeon_surface_manager *surf_man,
+                             struct radeon_surface *surf,
+                             unsigned mode)
+{
+    unsigned tileb;
+
+    /* check surface dimension */
+    if (surf->npix_x > 16384 || surf->npix_y > 16384 || surf->npix_z > 16384) {
+        return -EINVAL;
+    }
+
+    /* check mipmap last_level */
+    if (surf->last_level > 15) {
+        return -EINVAL;
+    }
+
+    /* force 1d on kernel that can't do 2d */
+    if (!surf_man->hw_info.allow_2d && mode > RADEON_SURF_MODE_1D) {
+        mode = RADEON_SURF_MODE_1D;
+        surf->flags = RADEON_SURF_CLR(surf->flags, MODE);
+        surf->flags |= RADEON_SURF_SET(mode, MODE);
+    }
+
+    /* check tile split */
+    if (mode == RADEON_SURF_MODE_2D) {
+        switch (surf->tile_split) {
+        case 64:
+        case 128:
+        case 256:
+        case 512:
+        case 1024:
+        case 2048:
+        case 4096:
+            break;
+        default:
+            return -EINVAL;
+        }
+        switch (surf->mtilea) {
+        case 1:
+        case 2:
+        case 4:
+        case 8:
+            break;
+        default:
+            return -EINVAL;
+        }
+        /* check aspect ratio */
+        if (surf_man->hw_info.num_banks < surf->mtilea) {
+            return -EINVAL;
+        }
+        /* check bank width */
+        switch (surf->bankw) {
+        case 1:
+        case 2:
+        case 4:
+        case 8:
+            break;
+        default:
+            return -EINVAL;
+        }
+        /* check bank height */
+        switch (surf->bankh) {
+        case 1:
+        case 2:
+        case 4:
+        case 8:
+            break;
+        default:
+            return -EINVAL;
+        }
+        tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
+        if ((tileb * surf->bankh * surf->bankw) < surf_man->hw_info.group_bytes) {
+            return -EINVAL;
+        }
+    }
+
+    return 0;
+}
+
+static int eg_surface_init(struct radeon_surface_manager *surf_man,
+                           struct radeon_surface *surf)
+{
+    unsigned mode;
+    int r;
+
+    /* 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;
+    }
+
+    r = eg_surface_sanity(surf_man, surf, mode);
+    if (r) {
+        return r;
+    }
+
+    /* 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 = 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);
+        break;
+    case RADEON_SURF_MODE_2D:
+        r = eg_surface_init_2d(surf_man, surf, 0, 0);
+        break;
+    default:
+        return -EINVAL;
+    }
+    return r;
+}
+
+static unsigned log2_int(unsigned x)
+{
+    unsigned l;
+
+    if (x < 2) {
+        return 0;
+    }
+    for (l = 2; ; l++) {
+        if ((unsigned)(1 << l) > x) {
+            return l - 1;
+        }
+    }
+    return 0;
+}
+
+/* compute best tile_split, bankw, bankh, mtilea
+ * depending on surface
+ */
+static int eg_surface_best(struct radeon_surface_manager *surf_man,
+                           struct radeon_surface *surf)
+{
+    unsigned mode, tileb, h_over_w;
+    int r;
+
+    /* 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;
+    surf->bankh = 1;
+    surf->mtilea = surf_man->hw_info.num_banks;
+    tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
+    for (; surf->bankh <= 8; surf->bankh *= 2) {
+        if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
+            break;
+        }
+    }
+    if (surf->mtilea > 8) {
+        surf->mtilea = 8;
+    }
+
+    r = eg_surface_sanity(surf_man, surf, mode);
+    if (r) {
+        return r;
+    }
+
+    if (mode != RADEON_SURF_MODE_2D) {
+        /* nothing to do for non 2D tiled surface */
+        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;
+
+    /* bankw or bankh greater than 1 increase alignment requirement, not
+     * sure if it's worth using smaller bankw & bankh to stick with 2D
+     * tiling on small surface rather than falling back to 1D tiling.
+     * Use recommanded value based on tile size for now.
+     *
+     * fmask buffer has different optimal value figure them out once we
+     * use it.
+     */
+    if (surf->flags & (RADEON_SURF_ZBUFFER | RADEON_SURF_SBUFFER)) {
+        /* assume 1 bytes for stencil, we optimize for stencil as stencil
+         * and depth shares surface values
+         */
+        tileb = MIN2(surf->tile_split, 64 * surf->nsamples);
+    } else {
+        tileb = MIN2(surf->tile_split, 64 * surf->bpe * surf->nsamples);
+    }
+
+    /* use bankw of 1 to minimize width alignment, might be interesting to
+     * increase it for large surface
+     */
+    surf->bankw = 1;
+    switch (tileb) {
+    case 64:
+        surf->bankh = 4;
+        break;
+    case 128:
+    case 256:
+        surf->bankh = 2;
+        break;
+    default:
+        surf->bankh = 1;
+        break;
+    }
+    /* double check the constraint */
+    for (; surf->bankh <= 8; surf->bankh *= 2) {
+        if ((tileb * surf->bankh * surf->bankw) >= surf_man->hw_info.group_bytes) {
+            break;
+        }
+    }
+
+    h_over_w = (((surf->bankh * surf_man->hw_info.num_banks) << 16) /
+                (surf->bankw * surf_man->hw_info.num_pipes)) >> 16;
+    surf->mtilea = 1 << (log2_int(h_over_w) >> 1);
+
+    return 0;
+}
+
+
+/* ===========================================================================
+ * public API
+ */
+struct radeon_surface_manager *radeon_surface_manager_new(int fd)
+{
+    struct radeon_surface_manager *surf_man;
+
+    surf_man = calloc(1, sizeof(struct radeon_surface_manager));
+    if (surf_man == NULL) {
+        return NULL;
+    }
+    surf_man->fd = fd;
+    if (radeon_get_value(fd, RADEON_INFO_DEVICE_ID, &surf_man->device_id)) {
+        goto out_err;
+    }
+    if (radeon_get_family(surf_man)) {
+        goto out_err;
+    }
+
+    if (surf_man->family <= CHIP_RV740) {
+        if (r6_init_hw_info(surf_man)) {
+            goto out_err;
+        }
+        surf_man->surface_init = &r6_surface_init;
+        surf_man->surface_best = &r6_surface_best;
+    } else {
+        if (eg_init_hw_info(surf_man)) {
+            goto out_err;
+        }
+        surf_man->surface_init = &eg_surface_init;
+        surf_man->surface_best = &eg_surface_best;
+    }
+
+    return surf_man;
+out_err:
+    free(surf_man);
+    return NULL;
+}
+
+void radeon_surface_manager_free(struct radeon_surface_manager *surf_man)
+{
+    free(surf_man);
+}
+
+static int radeon_surface_sanity(struct radeon_surface_manager *surf_man,
+                                 struct radeon_surface *surf,
+                                 unsigned type,
+                                 unsigned mode)
+{
+    if (surf_man == NULL || surf_man->surface_init == NULL || surf == NULL) {
+        return -EINVAL;
+    }
+
+    /* all dimension must be at least 1 ! */
+    if (!surf->npix_x || !surf->npix_y || !surf->npix_z) {
+        return -EINVAL;
+    }
+    if (!surf->blk_w || !surf->blk_h || !surf->blk_d) {
+        return -EINVAL;
+    }
+    if (!surf->array_size) {
+        return -EINVAL;
+    }
+    /* array size must be a power of 2 */
+    surf->array_size = next_power_of_two(surf->array_size);
+
+    switch (surf->nsamples) {
+    case 1:
+    case 2:
+    case 4:
+    case 8:
+        break;
+    default:
+        return -EINVAL;
+    }
+    /* check type */
+    switch (type) {
+    case RADEON_SURF_TYPE_1D:
+        if (surf->npix_y > 1) {
+            return -EINVAL;
+        }
+    case RADEON_SURF_TYPE_2D:
+        if (surf->npix_z > 1) {
+            return -EINVAL;
+        }
+        break;
+    case RADEON_SURF_TYPE_CUBEMAP:
+        if (surf->npix_z > 1) {
+            return -EINVAL;
+        }
+        /* deal with cubemap as they were texture array */
+        if (surf_man->family >= CHIP_RV770) {
+            surf->array_size = 8;
+        } else {
+            surf->array_size = 6;
+        }
+        break;
+    case RADEON_SURF_TYPE_3D:
+        break;
+    case RADEON_SURF_TYPE_1D_ARRAY:
+        if (surf->npix_y > 1) {
+            return -EINVAL;
+        }
+    case RADEON_SURF_TYPE_2D_ARRAY:
+        break;
+    default:
+        return -EINVAL;
+    }
+    return 0;
+}
+
+int radeon_surface_init(struct radeon_surface_manager *surf_man,
+                        struct radeon_surface *surf)
+{
+    unsigned mode, type;
+    int r;
+
+    type = RADEON_SURF_GET(surf->flags, TYPE);
+    mode = RADEON_SURF_GET(surf->flags, MODE);
+
+    r = radeon_surface_sanity(surf_man, surf, type, mode);
+    if (r) {
+        return r;
+    }
+    return surf_man->surface_init(surf_man, surf);
+}
+
+int radeon_surface_best(struct radeon_surface_manager *surf_man,
+                        struct radeon_surface *surf)
+{
+    unsigned mode, type;
+    int r;
+
+    type = RADEON_SURF_GET(surf->flags, TYPE);
+    mode = RADEON_SURF_GET(surf->flags, MODE);
+
+    r = radeon_surface_sanity(surf_man, surf, type, mode);
+    if (r) {
+        return r;
+    }
+    return surf_man->surface_best(surf_man, surf);
+}
diff --git a/radeon/radeon_surface.h b/radeon/radeon_surface.h
new file mode 100644 (file)
index 0000000..bfee8ab
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright Â© 2011 Red Hat All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
+ * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ *      Jérôme Glisse <jglisse@redhat.com>
+ */
+#ifndef RADEON_SURFACE_H
+#define RADEON_SURFACE_H
+
+/* Note :
+ *
+ * For texture array, the n layer are stored one after the other within each
+ * mipmap level. 0 value for field than can be hint is always valid.
+ */
+
+#define RADEON_SURF_MAX_LEVEL                   32
+
+#define RADEON_SURF_TYPE_MASK                   0xFF
+#define RADEON_SURF_TYPE_SHIFT                  0
+#define     RADEON_SURF_TYPE_1D                     0
+#define     RADEON_SURF_TYPE_2D                     1
+#define     RADEON_SURF_TYPE_3D                     2
+#define     RADEON_SURF_TYPE_CUBEMAP                3
+#define     RADEON_SURF_TYPE_1D_ARRAY               4
+#define     RADEON_SURF_TYPE_2D_ARRAY               5
+#define RADEON_SURF_MODE_MASK                   0xFF
+#define RADEON_SURF_MODE_SHIFT                  8
+#define     RADEON_SURF_MODE_LINEAR                 0
+#define     RADEON_SURF_MODE_LINEAR_ALIGNED         1
+#define     RADEON_SURF_MODE_1D                     2
+#define     RADEON_SURF_MODE_2D                     3
+#define RADEON_SURF_SCANOUT                     (1 << 16)
+#define RADEON_SURF_ZBUFFER                     (1 << 17)
+#define RADEON_SURF_SBUFFER                     (1 << 18)
+
+#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)
+#define RADEON_SURF_CLR(v, field)   ((v) & ~(RADEON_SURF_ ## field ## _MASK << RADEON_SURF_ ## field ## _SHIFT))
+
+/* first field up to mode need to match r6 struct so that we can reuse
+ * same function for linear & linear aligned
+ */
+struct radeon_surface_level {
+    uint64_t                    offset;
+    uint64_t                    slice_size;
+    uint32_t                    npix_x;
+    uint32_t                    npix_y;
+    uint32_t                    npix_z;
+    uint32_t                    nblk_x;
+    uint32_t                    nblk_y;
+    uint32_t                    nblk_z;
+    uint32_t                    pitch_bytes;
+    uint32_t                    mode;
+};
+
+struct radeon_surface {
+    uint32_t                    npix_x;
+    uint32_t                    npix_y;
+    uint32_t                    npix_z;
+    uint32_t                    blk_w;
+    uint32_t                    blk_h;
+    uint32_t                    blk_d;
+    uint32_t                    array_size;
+    uint32_t                    last_level;
+    uint32_t                    bpe;
+    uint32_t                    nsamples;
+    uint32_t                    flags;
+    /* Following is updated/fill by the allocator. It's allowed to
+     * set some of the value but they are use as hint and can be
+     * overridden (things lile bankw/bankh on evergreen for
+     * instance).
+     */
+    uint64_t                    bo_size;
+    uint64_t                    bo_alignment;
+    /* apply to eg */
+    uint32_t                    bankw;
+    uint32_t                    bankh;
+    uint32_t                    mtilea;
+    uint32_t                    tile_split;
+    uint32_t                    stencil_tile_split;
+    uint64_t                    stencil_offset;
+    struct radeon_surface_level level[RADEON_SURF_MAX_LEVEL];
+};
+
+struct radeon_surface_manager *radeon_surface_manager_new(int fd);
+void radeon_surface_manager_free(struct radeon_surface_manager *surf_man);
+int radeon_surface_init(struct radeon_surface_manager *surf_man,
+                        struct radeon_surface *surf);
+int radeon_surface_best(struct radeon_surface_manager *surf_man,
+                        struct radeon_surface *surf);
+
+#endif
old mode 100755 (executable)
new mode 100644 (file)
index 6a01f24..f723ded
@@ -43,6 +43,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <errno.h>
 
 #include "drm_slp_bufmgr.h"
+#include "list.h"
 
 #define PREFIX_LIB    "libdrm_slp_"
 #define SUFFIX_LIB    ".so"
@@ -52,6 +53,17 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 #define SEM_NAME               "pixmap_1"
 #define SEM_DEBUG 0
 
+#define DRM_RETURN_IF_FAIL(cond)          {if (!(cond)) { fprintf (stderr, "[%s] : '%s' failed.\n", __FUNCTION__, #cond); return; }}
+#define DRM_RETURN_VAL_IF_FAIL(cond, val) {if (!(cond)) { fprintf (stderr, "[%s] : '%s' failed.\n", __FUNCTION__, #cond); return val; }}
+
+#define MGR_IS_VALID(mgr) (mgr && \
+                                                mgr->link.next && \
+                                                mgr->link.next->prev == &mgr->link)
+#define BO_IS_VALID(bo) (bo && \
+                                            MGR_IS_VALID(bo->bufmgr) && \
+                                            bo->list.next && \
+                                            bo->list.next->prev == &bo->list)
+
 typedef struct{
        void* data;
 
@@ -59,6 +71,8 @@ typedef struct{
        drm_data_free free_func ;
 }drm_slp_user_data;
 
+static struct list_head *gBufMgrs = NULL;
+
 static int
 _sem_wait_wrapper(sem_t* sem)
 {
@@ -243,498 +257,591 @@ _load_bufmgr(int fd, const char *file, void *arg)
        return bufmgr;
 }
 
-drm_slp_bufmgr drm_slp_bufmgr_init(int fd, void *arg)
+drm_slp_bufmgr
+drm_slp_bufmgr_init(int fd, void *arg)
 {
-       drm_slp_bufmgr bufmgr = NULL;
-       const char *p = NULL;
-
-       if (fd < 0)
-               return NULL;
-
-       p = getenv ("SLP_BUFMGR_MODULE");
-       if (p) {
-               char file[PATH_MAX] = {0,};
-               snprintf(file, sizeof(file), PREFIX_LIB"%s"SUFFIX_LIB, p);
-               bufmgr = _load_bufmgr (fd, file, arg);
-       }
-
-       if (!bufmgr)
-               bufmgr = _load_bufmgr (fd, DEFAULT_LIB, arg);
-
-       if (!bufmgr) {
-               struct dirent **namelist;
-               int found = 0;
-               int n;
-
-               n = scandir(BUFMGR_DIR, &namelist, 0, alphasort);
-               if (n < 0)
-                       fprintf(stderr,"[libdrm] no files : %s\n", BUFMGR_DIR);
-               else {
-                       while(n--) {
-                               if (!found && strstr (namelist[n]->d_name, PREFIX_LIB)) {
-                                       char *p = strstr (namelist[n]->d_name, SUFFIX_LIB);
-                                       if (!strcmp (p, SUFFIX_LIB))
-                                       {
-                                               bufmgr = _load_bufmgr (fd, namelist[n]->d_name, arg);
-                                               if (bufmgr)
-                                                       found = 1;
-                                       }
-                               }
-                               free(namelist[n]);
-                       }
-                       free(namelist);
-               }
-       }
-
-       if (!bufmgr)
-       {
-               fprintf(stderr,"[libdrm] backend is NULL.\n");
-               return NULL;
-       }
-
-       if (pthread_mutex_init(&bufmgr->lock, NULL) != 0) {
-               bufmgr->bufmgr_destroy(bufmgr);
-               free(bufmgr);
-               return NULL;
-       }
-
-       return bufmgr;
+    drm_slp_bufmgr bufmgr = NULL;
+    const char *p = NULL;
+
+    if (fd < 0)
+        return NULL;
+
+    if(gBufMgrs == NULL)
+    {
+        gBufMgrs = malloc(sizeof(struct list_head));
+        LIST_INITHEAD(gBufMgrs);
+    }
+    else
+    {
+        LIST_FOR_EACH_ENTRY(bufmgr, gBufMgrs, link)
+        {
+            if(bufmgr->drm_fd == fd)
+            {
+                bufmgr->ref_count++;
+                fprintf(stderr, "[libdrm] bufmgr ref: fd=%d, ref_count:%d\n", fd, bufmgr->ref_count);
+                return bufmgr;
+            }
+        }
+        bufmgr = NULL;
+    }
+    fprintf(stderr, "[libdrm] bufmgr init: fd=%d\n", fd);
+
+    p = getenv ("SLP_BUFMGR_MODULE");
+    if (p)
+    {
+        char file[PATH_MAX] = {0,};
+        snprintf(file, sizeof(file), PREFIX_LIB"%s"SUFFIX_LIB, p);
+        bufmgr = _load_bufmgr (fd, file, arg);
+    }
+
+    if (!bufmgr)
+        bufmgr = _load_bufmgr (fd, DEFAULT_LIB, arg);
+
+    if (!bufmgr)
+    {
+        struct dirent **namelist;
+        int found = 0;
+        int n;
+
+        n = scandir(BUFMGR_DIR, &namelist, 0, alphasort);
+        if (n < 0)
+            fprintf(stderr,"[libdrm] no files : %s\n", BUFMGR_DIR);
+        else
+        {
+            while(n--)
+            {
+                if (!found && strstr (namelist[n]->d_name, PREFIX_LIB))
+                {
+                    char *p = strstr (namelist[n]->d_name, SUFFIX_LIB);
+                    if (!strcmp (p, SUFFIX_LIB))
+                    {
+                        bufmgr = _load_bufmgr (fd, namelist[n]->d_name, arg);
+                        if (bufmgr)
+                            found = 1;
+                    }
+                }
+                free(namelist[n]);
+            }
+            free(namelist);
+        }
+    }
+
+    if (!bufmgr)
+    {
+        fprintf(stderr,"[libdrm] backend is NULL.\n");
+        return NULL;
+    }
+
+    if (pthread_mutex_init(&bufmgr->lock, NULL) != 0)
+    {
+        bufmgr->bufmgr_destroy(bufmgr);
+        free(bufmgr);
+        return NULL;
+    }
+
+    bufmgr->ref_count = 1;
+    bufmgr->drm_fd = fd;
+
+    LIST_INITHEAD(&bufmgr->bos);
+    LIST_ADD(&bufmgr->link, gBufMgrs);
+
+    return bufmgr;
 }
 
-void drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr)
+void
+drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr)
 {
-       if(!bufmgr)
-               return;
-
-       bufmgr->bufmgr_destroy(bufmgr);
-
-       if(bufmgr->semObj.isOpened)
-       {
-               _sem_close(bufmgr);
-       }
+    DRM_RETURN_IF_FAIL(MGR_IS_VALID(bufmgr));
+
+    fprintf(stderr, "[DRM] bufmgr destroy: bufmgr:%p, drm_fd:%d\n",
+                bufmgr, bufmgr->drm_fd);
+
+    /*Check and Free bos*/
+    if(!LIST_IS_EMPTY(&bufmgr->bos))
+    {
+        drm_slp_bo bo, tmp;
+
+        LIST_FOR_EACH_ENTRY_SAFE(bo, tmp, &bufmgr->bos,  list)
+        {
+            fprintf(stderr, "[libdrm] Un-freed bo(%p, ref:%d) \n", bo, bo->ref_cnt);
+            bo->ref_cnt = 1;
+            drm_slp_bo_unref(bo);
+        }
+    }
+
+    LIST_DEL(&bufmgr->link);
+    bufmgr->bufmgr_destroy(bufmgr);
+
+    if(bufmgr->semObj.isOpened)
+    {
+        _sem_close(bufmgr);
+    }
+
+    pthread_mutex_destroy(&bufmgr->lock);
+    free(bufmgr);
+}
 
-       pthread_mutex_destroy(&bufmgr->lock);
-       free(bufmgr);
+int
+drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr)
+{
+    DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0);
+
+    pthread_mutex_lock(&bufmgr->lock);
+
+    if(bufmgr->bufmgr_lock)
+    {
+        int ret;
+        ret = bufmgr->bufmgr_lock(bufmgr);
+        pthread_mutex_unlock(&bufmgr->lock);
+        return ret;
+    }
+
+    if(!bufmgr->semObj.isOpened)
+    {
+        if(_sem_open(bufmgr) != 1)
+        {
+            pthread_mutex_unlock(&bufmgr->lock);
+            return 0;
+        }
+        bufmgr->semObj.isOpened = 1;
+    }
+
+    if(_sem_lock(bufmgr) != 1)
+    {
+        pthread_mutex_unlock(&bufmgr->lock);
+        return 0;
+    }
+
+    pthread_mutex_unlock(&bufmgr->lock);
+
+    return 1;
 }
 
-int drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr)
+int
+drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr)
 {
-       if(!bufmgr)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), 0);
 
-       pthread_mutex_lock(&bufmgr->lock);
+    pthread_mutex_lock(&bufmgr->lock);
 
-       if(!bufmgr->semObj.isOpened)
-       {
-               if(_sem_open(bufmgr) != 1)
-               {
-                       pthread_mutex_unlock(&bufmgr->lock);
-                       return 0;
-               }
-               bufmgr->semObj.isOpened = 1;
-       }
+    if(bufmgr->bufmgr_unlock)
+    {
+        int ret;
+        ret = bufmgr->bufmgr_unlock(bufmgr);
+        pthread_mutex_unlock(&bufmgr->lock);
+        return ret;
+    }
 
-       if(_sem_lock(bufmgr) != 1)
-       {
-               pthread_mutex_unlock(&bufmgr->lock);
-               return 0;
-       }
+    if(_sem_unlock(bufmgr) != 1)
+    {
+        pthread_mutex_unlock(&bufmgr->lock);
+        return 0;
+    }
 
-       pthread_mutex_unlock(&bufmgr->lock);
+    pthread_mutex_unlock(&bufmgr->lock);
 
-       return 1;
+    return 1;
 }
 
-int drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr)
+int
+drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags)
 {
-       if(!bufmgr)
-               return 0;
+    int ret;
 
-       pthread_mutex_lock(&bufmgr->lock);
+    DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr) || BO_IS_VALID(bo), 0);
 
-       if(_sem_unlock(bufmgr) != 1)
-       {
-               pthread_mutex_unlock(&bufmgr->lock);
-               return 0;
-       }
+    if (!bo)
+        flags |= DRM_SLP_CACHE_ALL;
 
-       pthread_mutex_unlock(&bufmgr->lock);
+    if (bo)
+    {
+        DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
 
-       return 1;
+        if(!bo->bufmgr)
+            return 0;
+
+        pthread_mutex_lock(&bo->bufmgr->lock);
+        ret = bo->bufmgr->bufmgr_cache_flush(bufmgr, bo, flags);
+        pthread_mutex_unlock(&bo->bufmgr->lock);
+    }
+    else
+    {
+        pthread_mutex_lock(&bufmgr->lock);
+        ret = bufmgr->bufmgr_cache_flush(bufmgr, NULL, flags);
+        pthread_mutex_unlock(&bufmgr->lock);
+    }
+
+    return ret;
 }
 
-int drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags)
+int
+drm_slp_bo_size(drm_slp_bo bo)
 {
-       int ret;
+    int size;
+    drm_slp_bufmgr bufmgr;
 
-       if (!bufmgr && !bo)
-               return 0;
-
-       if (!bo)
-               flags |= DRM_SLP_CACHE_ALL;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
 
-       if (bo)
-       {
-               if(!bo->bufmgr)
-                       return 0;
+    bufmgr = bo->bufmgr;
 
-               pthread_mutex_lock(&bo->bufmgr->lock);
-               ret = bo->bufmgr->bufmgr_cache_flush(bufmgr, bo, flags);
-               pthread_mutex_unlock(&bo->bufmgr->lock);
-       }
-       else
-       {
-               pthread_mutex_lock(&bufmgr->lock);
-               ret = bufmgr->bufmgr_cache_flush(bufmgr, NULL, flags);
-               pthread_mutex_unlock(&bufmgr->lock);
-       }
+    pthread_mutex_lock(&bufmgr->lock);
+    size = bo->bufmgr->bo_size(bo);
+    pthread_mutex_unlock(&bufmgr->lock);
 
-       return ret;
+    return size;
 }
 
-int drm_slp_bo_size(drm_slp_bo bo)
+drm_slp_bo
+drm_slp_bo_ref(drm_slp_bo bo)
 {
-       int size;
-       drm_slp_bufmgr bufmgr;
+    drm_slp_bufmgr bufmgr;
 
-       if(!bo || !bo->bufmgr)
-               return 0;
-       bufmgr = bo->bufmgr;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), NULL);
+
+    bufmgr = bo->bufmgr;
+
+    pthread_mutex_lock(&bufmgr->lock);
+
+    bo->ref_cnt++;
 
-       pthread_mutex_lock(&bufmgr->lock);
-       size = bo->bufmgr->bo_size(bo);
-       pthread_mutex_unlock(&bufmgr->lock);
+    pthread_mutex_unlock(&bufmgr->lock);
 
-       return size;
+    return bo;
 }
 
-drm_slp_bo drm_slp_bo_ref(drm_slp_bo bo)
+void
+drm_slp_bo_unref(drm_slp_bo bo)
 {
-       drm_slp_bufmgr bufmgr;
+    drm_slp_bufmgr bufmgr;
 
-       if(!bo || !bo->bufmgr)
-               return NULL;
-       bufmgr = bo->bufmgr;
+    DRM_RETURN_IF_FAIL(BO_IS_VALID(bo));
 
-       pthread_mutex_lock(&bufmgr->lock);
+    bufmgr = bo->bufmgr;
 
-       bo->ref_cnt++;
+    if(0 >= bo->ref_cnt)
+        return;
 
-       pthread_mutex_unlock(&bufmgr->lock);
+    pthread_mutex_lock(&bufmgr->lock);
 
-       return bo;
-}
+    bo->ref_cnt--;
+    if(bo->ref_cnt == 0)
+    {
+        if(bo->user_data)
+        {
+            void* rd;
+            drm_slp_user_data* old_data;
+            unsigned long key;
 
-void drm_slp_bo_unref(drm_slp_bo bo)
-{
-       drm_slp_bufmgr bufmgr;
+            while(1==drmSLFirst(bo->user_data, &key, &rd))
+            {
+                old_data = (drm_slp_user_data*)rd;
 
-       if(!bo || !bo->bufmgr)
-               return;
-       bufmgr = bo->bufmgr;
+                if(old_data->is_valid && old_data->free_func)
+                {
+                    if(old_data->data)
+                        old_data->free_func(old_data->data);
+                    old_data->data = NULL;
+                    free(old_data);
+                }
+                drmSLDelete(bo->user_data, key);
+            }
 
-       pthread_mutex_lock(&bufmgr->lock);
+            drmSLDestroy(bo->user_data);
+            bo->user_data = (void*)0;
+        }
 
-       if(0 >= bo->ref_cnt)
-               return;
-       bo->ref_cnt--;
-       if(bo->ref_cnt == 0)
-       {
-               bufmgr->bo_free(bo);
-
-               if(bo->user_data)
-               {
-                       void* rd;
-                       drm_slp_user_data* old_data;
-                       unsigned long key;
-
-                       while(1==drmSLFirst(bo->user_data, &key, &rd))
-                       {
-                               old_data = (drm_slp_user_data*)rd;
-
-                               if(old_data->is_valid && old_data->free_func)
-                               {
-                                       if(old_data->data)
-                                           old_data->free_func(old_data->data);
-                                       old_data->data = NULL;
-                                       free(old_data);
-                               }
-                               drmSLDelete(bo->user_data, key);
-                       }
-
-                       drmSLDestroy(bo->user_data);
-                       bo->user_data = (void*)0;
-               }
-
-               free(bo);
-       }
+        LIST_DEL(&bo->list);
+        bufmgr->bo_free(bo);
+
+        free(bo);
+    }
 
-       pthread_mutex_unlock(&bufmgr->lock);
+    pthread_mutex_unlock(&bufmgr->lock);
 }
 
-drm_slp_bo drm_slp_bo_alloc(drm_slp_bufmgr bufmgr, const char * name, int size)
+drm_slp_bo
+drm_slp_bo_alloc(drm_slp_bufmgr bufmgr, const char * name, int size, int flags)
 {
-       drm_slp_bo bo=NULL;
+    drm_slp_bo bo=NULL;
 
-       if(!bufmgr || size <= 0)
-               return NULL;
+    DRM_RETURN_VAL_IF_FAIL( MGR_IS_VALID(bufmgr) && (size > 0), NULL);
 
-       bo = calloc(sizeof(struct _drm_slp_bo), 1);
-       if(!bo)
-               return NULL;
+    bo = calloc(sizeof(struct _drm_slp_bo), 1);
+    if(!bo)
+        return NULL;
 
-       bo->bufmgr = bufmgr;
+    bo->bufmgr = bufmgr;
 
-       pthread_mutex_lock(&bufmgr->lock);
-       if(!bufmgr->bo_alloc(bo, name, size))
-       {
-               free(bo);
-               pthread_mutex_unlock(&bufmgr->lock);
-               return NULL;
-       }
-       bo->ref_cnt = 1;
-       pthread_mutex_unlock(&bufmgr->lock);
+    pthread_mutex_lock(&bufmgr->lock);
+    if(!bufmgr->bo_alloc(bo, name, size, flags))
+    {
+        free(bo);
+        pthread_mutex_unlock(&bufmgr->lock);
+        return NULL;
+    }
+    bo->ref_cnt = 1;
+    LIST_ADD(&bo->list, &bufmgr->bos);
+    pthread_mutex_unlock(&bufmgr->lock);
 
-       return bo;
+    return bo;
 }
 
-drm_slp_bo drm_slp_bo_attach(drm_slp_bufmgr bufmgr,
+drm_slp_bo
+drm_slp_bo_attach(drm_slp_bufmgr bufmgr,
                              const char*    name,
-                             void*          ptr,
-                             int            size,
-                             void*          native_handle)
+                             int type,
+                             int size,
+                             unsigned int handle)
 {
-       drm_slp_bo bo;
+    drm_slp_bo bo;
 
-       if(!bufmgr)
-               return NULL;
+    DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL);
 
-       bo = calloc(sizeof(struct _drm_slp_bo), 1);
-       if(!bo)
-               return NULL;
+    bo = calloc(sizeof(struct _drm_slp_bo), 1);
+    if(!bo)
+        return NULL;
 
-       bo->bufmgr = bufmgr;
+    bo->bufmgr = bufmgr;
 
-       pthread_mutex_lock(&bufmgr->lock);
-       if(!bufmgr->bo_attach(bo, name, ptr, size, native_handle))
-       {
-               free(bo);
-               pthread_mutex_unlock(&bufmgr->lock);
-               return NULL;
-       }
-       bo->ref_cnt = 1;
-       pthread_mutex_unlock(&bufmgr->lock);
+    pthread_mutex_lock(&bufmgr->lock);
+    if(!bufmgr->bo_attach(bo, name, type, size, handle))
+    {
+        free(bo);
+        pthread_mutex_unlock(&bufmgr->lock);
+        return NULL;
+    }
+    bo->ref_cnt = 1;
+    LIST_ADD(&bo->list, &bufmgr->bos);
+    pthread_mutex_unlock(&bufmgr->lock);
 
-       return bo;
+    return bo;
 }
 
-drm_slp_bo drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key)
+drm_slp_bo
+drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key)
 {
-       drm_slp_bo bo;
+    drm_slp_bo bo;
 
-       if(!bufmgr)
-               return NULL;
+    DRM_RETURN_VAL_IF_FAIL(MGR_IS_VALID(bufmgr), NULL);
 
-       bo = calloc(sizeof(struct _drm_slp_bo), 1);
-       if(!bo)
-               return NULL;
+    bo = calloc(sizeof(struct _drm_slp_bo), 1);
+    if(!bo)
+        return NULL;
 
-       bo->bufmgr = bufmgr;
+    bo->bufmgr = bufmgr;
 
-       pthread_mutex_lock(&bufmgr->lock);
-       if(!bufmgr->bo_import(bo, key))
-       {
-               free(bo);
-               pthread_mutex_unlock(&bufmgr->lock);
-               return NULL;
-       }
-       bo->ref_cnt = 1;
-       pthread_mutex_unlock(&bufmgr->lock);
+    pthread_mutex_lock(&bufmgr->lock);
+    if(!bufmgr->bo_import(bo, key))
+    {
+        free(bo);
+        pthread_mutex_unlock(&bufmgr->lock);
+        return NULL;
+    }
+    bo->ref_cnt = 1;
+    LIST_ADD(&bo->list, &bufmgr->bos);
+    pthread_mutex_unlock(&bufmgr->lock);
 
-       return bo;
+    return bo;
 }
 
-unsigned int drm_slp_bo_export(drm_slp_bo bo)
+unsigned int
+drm_slp_bo_export(drm_slp_bo bo)
 {
-       int ret;
+    int ret;
 
-       if(!bo || !bo->bufmgr)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
 
-       pthread_mutex_lock(&bo->bufmgr->lock);
-       ret = bo->bufmgr->bo_export(bo);
-       pthread_mutex_unlock(&bo->bufmgr->lock);
+    pthread_mutex_lock(&bo->bufmgr->lock);
+    ret = bo->bufmgr->bo_export(bo);
+    pthread_mutex_unlock(&bo->bufmgr->lock);
 
-       return ret;
+    return ret;
 }
 
-void * drm_slp_bo_map(drm_slp_bo bo, int device, int opt)
+unsigned int
+drm_slp_bo_get_handle(drm_slp_bo bo, int device)
 {
-       void* ret;
+    unsigned int ret;
 
-       if(!bo || !bo->bufmgr)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
 
-       pthread_mutex_lock(&bo->bufmgr->lock);
-       ret = bo->bufmgr->bo_map(bo, device, opt);
-       pthread_mutex_unlock(&bo->bufmgr->lock);
+    pthread_mutex_lock(&bo->bufmgr->lock);
+    ret = bo->bufmgr->bo_get_handle(bo, device);
+    pthread_mutex_unlock(&bo->bufmgr->lock);
 
-       return ret;
+    return ret;
 }
 
-int drm_slp_bo_unmap(drm_slp_bo bo, int device)
+unsigned int
+drm_slp_bo_map(drm_slp_bo bo, int device, int opt)
 {
-       int ret;
+    unsigned int ret;
 
-       if(!bo || !bo->bufmgr)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
+
+    pthread_mutex_lock(&bo->bufmgr->lock);
+    if(bo->bufmgr->bo_lock)
+    {
+        bo->bufmgr->bo_lock(bo, 0, (void*)0);
+    }
 
-       pthread_mutex_lock(&bo->bufmgr->lock);
-       ret = bo->bufmgr->bo_unmap(bo, device);
-       pthread_mutex_unlock(&bo->bufmgr->lock);
+    ret = bo->bufmgr->bo_map(bo, device, opt);
+    pthread_mutex_unlock(&bo->bufmgr->lock);
 
-       return 0;
+    return ret;
 }
 
-int drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2)
+int
+drm_slp_bo_unmap(drm_slp_bo bo, int device)
 {
-       void* temp;
+    int ret;
 
-       if(!bo1 || !bo1->bufmgr)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
 
-       if(!bo2 || !bo2->bufmgr)
-               return 0;
+    pthread_mutex_lock(&bo->bufmgr->lock);
+    ret = bo->bufmgr->bo_unmap(bo, device);
 
-       if(bo1->bufmgr != bo2->bufmgr)
-               return 0;
+    if(bo->bufmgr->bo_unlock)
+    {
+        bo->bufmgr->bo_unlock(bo);
+    }
+    pthread_mutex_unlock(&bo->bufmgr->lock);
 
-       if(bo1->bufmgr->bo_size(bo1) != bo2->bufmgr->bo_size(bo2))
-               return 0;
+    return 0;
+}
+
+int
+drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2)
+{
+    void* temp;
 
-       pthread_mutex_lock(&bo1->bufmgr->lock);
-       temp = bo1->private;
-       bo1->private = bo2->private;
-       bo2->private = temp;
-       pthread_mutex_unlock(&bo1->bufmgr->lock);
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo1), 0);
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo2), 0);
 
-       return 1;
+    if(bo1->bufmgr->bo_size(bo1) != bo2->bufmgr->bo_size(bo2))
+        return 0;
+
+    pthread_mutex_lock(&bo1->bufmgr->lock);
+    temp = bo1->priv;
+    bo1->priv = bo2->priv;
+    bo2->priv = temp;
+    pthread_mutex_unlock(&bo1->bufmgr->lock);
+
+    return 1;
 }
 
-int drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func)
+int
+drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func)
 {
-       int ret;
-       drm_slp_user_data* data;
+    int ret;
+    drm_slp_user_data* data;
 
-       if(!bo)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
 
-       if(!bo->user_data)
-               bo->user_data = drmSLCreate();
+    if(!bo->user_data)
+        bo->user_data = drmSLCreate();
 
-       data = calloc(1, sizeof(drm_slp_user_data));
-       if(!data)
-               return 0;
+    data = calloc(1, sizeof(drm_slp_user_data));
+    if(!data)
+        return 0;
 
-       data->free_func = data_free_func;
-       data->data = (void*)0;
-       data->is_valid = 0;
+    data->free_func = data_free_func;
+    data->data = (void*)0;
+    data->is_valid = 0;
 
-       ret = drmSLInsert(bo->user_data, key, data);
-       if(ret == 1) /* Already in list */
-       {
-               free(data);
-               return 0;
-       }
+    ret = drmSLInsert(bo->user_data, key, data);
+    if(ret == 1) /* Already in list */
+    {
+        free(data);
+        return 0;
+    }
 
-       return 1;
+    return 1;
 }
 
-int drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data)
+int
+drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data)
 {
-       void *rd;
-       drm_slp_user_data* old_data;
+    void *rd;
+    drm_slp_user_data* old_data;
 
-       if(!bo || !bo->user_data)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo), 0);
 
-       if(drmSLLookup(bo->user_data, key, &rd))
-               return 0;
+    if(!bo->user_data)
+        return 0;
 
-       old_data = (drm_slp_user_data*)rd;
-       if (!old_data)
-               return 0;
+    if(drmSLLookup(bo->user_data, key, &rd))
+        return 0;
 
-       if(old_data->is_valid)
-       {
-               if(old_data->free_func)
-               {
-                       if(old_data->data)
-                           old_data->free_func(old_data->data);
-                       old_data->data = NULL;
-               }
-       }
-       else
-               old_data->is_valid = 1;
+    old_data = (drm_slp_user_data*)rd;
+    if (!old_data)
+        return 0;
 
-       old_data->data = data;
+    if(old_data->is_valid)
+    {
+        if(old_data->free_func)
+        {
+            if(old_data->data)
+                old_data->free_func(old_data->data);
+                old_data->data = NULL;
+        }
+    }
+    else
+        old_data->is_valid = 1;
 
-       return 1;
+    old_data->data = data;
+
+    return 1;
 }
 
-int drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data)
+int
+drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data)
 {
-       void *rd;
-       drm_slp_user_data* old_data;
-
-    if(!data) return 0;
+    void *rd;
+    drm_slp_user_data* old_data;
 
-       if(!bo || !bo->user_data)
-       {
-           *data = NULL;
-               return 0;
-       }
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && data && bo->user_data, 0);
 
-       if(drmSLLookup(bo->user_data, key, &rd))
-       {
-           *data = NULL;
-               return 0;
-       }
+    if(drmSLLookup(bo->user_data, key, &rd))
+    {
+        *data = NULL;
+        return 0;
+    }
 
-       old_data = (drm_slp_user_data*)rd;
-       if (!old_data)
-       {
-           *data = NULL;
-               return 0;
-       }
+    old_data = (drm_slp_user_data*)rd;
+    if (!old_data)
+    {
+        *data = NULL;
+        return 0;
+    }
 
-       *data = old_data->data;
+    *data = old_data->data;
 
-       return 1;
+    return 1;
 }
 
-int drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key)
+int
+drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key)
 {
-       void *rd;
-       drm_slp_user_data* old_data=(void*)0;
+    void *rd;
+    drm_slp_user_data* old_data=(void*)0;
 
-       if(!bo || !bo->user_data)
-               return 0;
+    DRM_RETURN_VAL_IF_FAIL(BO_IS_VALID(bo) && bo->user_data, 0);
 
-       if(drmSLLookup(bo->user_data, key, &rd))
-               return 0;
+    if(drmSLLookup(bo->user_data, key, &rd))
+        return 0;
 
-       old_data = (drm_slp_user_data*)rd;
-       if (!old_data)
-               return 0;
+    old_data = (drm_slp_user_data*)rd;
+    if (!old_data)
+        return 0;
 
-       if(old_data->is_valid && old_data->free_func)
-       {
+    if(old_data->is_valid && old_data->free_func)
+    {
         if(old_data->data)
-                   old_data->free_func(old_data->data);
-               free(old_data);
-       }
-       drmSLDelete(bo->user_data, key);
+            old_data->free_func(old_data->data);
+        free(old_data);
+    }
+    drmSLDelete(bo->user_data, key);
 
-       return 1;
+    return 1;
 }
old mode 100755 (executable)
new mode 100644 (file)
index 23a4c4b..a4adef5
@@ -38,119 +38,164 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 typedef struct _drm_slp_bo * drm_slp_bo;
 typedef struct _drm_slp_bufmgr * drm_slp_bufmgr;
 
+struct list_head
+{
+    struct list_head *prev;
+    struct list_head *next;
+};
+
 struct _drm_slp_bo
 {
-       drm_slp_bufmgr bufmgr;
-       int ref_cnt;            /*atomic count*/
-       void *user_data;
+    struct list_head list;
+    drm_slp_bufmgr bufmgr;
+    int ref_cnt;               /*atomic count*/
+    void *user_data;
 
-       /* private data */
-       void *private;
+    /* private data */
+    void *priv;
 };
 
 typedef enum
 {
-       STATUS_UNLOCK,
-       STATUS_READY_TO_LOCK,
-       STATUS_LOCK,
+    STATUS_UNLOCK,
+    STATUS_READY_TO_LOCK,
+    STATUS_LOCK,
 } lock_status;
 
 struct _drm_slp_bufmgr
 {
-       pthread_mutex_t lock;
-       struct {
-               int isOpened;
-               lock_status status;
-               sem_t* handle;
-       } semObj;
-
-       void         (*bufmgr_destroy)(drm_slp_bufmgr bufmgr);
-       int          (*bufmgr_cache_flush)(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags);
-
-       int          (*bo_size)(drm_slp_bo bo);
-
-       void         (*bo_free)(drm_slp_bo bo);
-       int          (*bo_alloc)(drm_slp_bo bo,
-                                const char*    name,
-                                int            size);
-
-       int          (*bo_attach)(drm_slp_bo bo,
-                                 const char*    name,
-                                 void*          ptr,
-                                 int            size,
-                                 void*          native_handle);
-
-       int          (*bo_import)(drm_slp_bo bo, unsigned int key);
-       unsigned int (*bo_export)(drm_slp_bo bo);
-
-       void*        (*bo_map)(drm_slp_bo bo, int device, int opt);
-       int          (*bo_unmap)(drm_slp_bo bo, int device);
-
-
-       /* Padding for future extension */
-       void (*reserved1) (void);
-       void (*reserved2) (void);
-       void (*reserved3) (void);
-       void (*reserved4) (void);
-       void (*reserved5) (void);
-       void (*reserved6) (void);
-
-       /* private data */
-       void *private;
+    struct list_head bos;  /*list head of bo*/
+
+    pthread_mutex_t lock;
+    struct {
+        int isOpened;
+        lock_status status;
+        sem_t* handle;
+    } semObj;
+
+    void         (*bufmgr_destroy)(drm_slp_bufmgr bufmgr);
+    int          (*bufmgr_cache_flush)(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags);
+
+    int          (*bo_size)(drm_slp_bo bo);
+
+    void         (*bo_free)(drm_slp_bo bo);
+    int          (*bo_alloc)(drm_slp_bo bo,
+                                        const char*    name,
+                                        int            size,
+                                        int flags);
+    int          (*bo_attach)(drm_slp_bo bo,
+                                        const char*    name,
+                                        int          type,
+                                        int            size,
+                                        unsigned int          handle);
+    int          (*bo_import)(drm_slp_bo bo, unsigned int key);
+    unsigned int (*bo_export)(drm_slp_bo bo);
+
+    unsigned int (*bo_get_handle)(drm_slp_bo bo, int device);
+    unsigned int        (*bo_map)(drm_slp_bo bo, int device, int opt);
+    int          (*bo_unmap)(drm_slp_bo bo, int device);
+
+
+    /* Padding for future extension */
+    int (*bufmgr_lock) (drm_slp_bufmgr bufmgr);
+    int (*bufmgr_unlock) (drm_slp_bufmgr bufmgr);
+    int (*bo_lock) (drm_slp_bo bo, unsigned int checkOnly, unsigned int* isLocked);
+    int (*bo_unlock) (drm_slp_bo bo);
+    void (*reserved5) (void);
+    void (*reserved6) (void);
+
+    /* private data */
+    void *priv;
+
+    struct list_head link;  /*link of bufmgr*/
+
+    int drm_fd;
+    int ref_count;
 };
 
+/* DRM_SLP_MEM_TYPE */
+#define DRM_SLP_MEM_GEM             0
+#define DRM_SLP_MEM_USERPTR     1
+#define DRM_SLP_MEM_DMABUF      2
+#define DRM_SLP_MEM_GPU             3
+
 /* DRM_SLP_DEVICE_TYPE */
-#define DRM_SLP_DEVICE_CPU     1
-#define DRM_SLP_DEVICE_2D      2
-#define DRM_SLP_DEVICE_3D      3
+#define DRM_SLP_DEVICE_DEFAULT   0  //Default handle
+#define DRM_SLP_DEVICE_CPU 1
+#define DRM_SLP_DEVICE_2D   2
+#define DRM_SLP_DEVICE_3D   3
+#define DRM_SLP_DEVICE_MM  4
 
 /* DRM_SLP_OPTION */
-#define DRM_SLP_OPTION_INDEX0  0
-#define DRM_SLP_OPTION_INDEX1  1
-#define DRM_SLP_OPTION_INDEX2  2
-#define DRM_SLP_OPTION_READ    (1 << 24)
-#define DRM_SLP_OPTION_WRITE   (1 << 25)
+#define DRM_SLP_OPTION_READ    (1 << 0)
+#define DRM_SLP_OPTION_WRITE   (1 << 1)
 
+/* DRM_SLP_CACHE */
 #define DRM_SLP_CACHE_INV   0x01
 #define DRM_SLP_CACHE_CLN   0x02
 #define DRM_SLP_CACHE_ALL   0x10
 #define DRM_SLP_CACHE_FLUSH     (DRM_SLP_CACHE_INV|DRM_SLP_CACHE_CLN)
 #define DRM_SLP_CACHE_FLUSH_ALL (DRM_SLP_CACHE_FLUSH|DRM_SLP_CACHE_ALL)
 
-drm_slp_bufmgr drm_slp_bufmgr_init(int fd, void * arg);
-
-void    drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr);
-int     drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr);
-int     drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr);
-int     drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags);
-
-int     drm_slp_bo_size (drm_slp_bo bo);
-
-drm_slp_bo  drm_slp_bo_ref(drm_slp_bo bo);
-void        drm_slp_bo_unref(drm_slp_bo bo);
+enum DRM_SLP_BO_FLAGS{
+    DRM_SLP_BO_DEFAULT = 0,
+    DRM_SLP_BO_SCANOUT = (1<<0),
+    DRM_SLP_BO_NONCACHABLE = (1<<1),
+    DRM_SLP_BO_WC = (1<<2),
+};
 
-drm_slp_bo drm_slp_bo_alloc(drm_slp_bufmgr bufmgr,
-                            const char*    name,
-                            int            size);
-drm_slp_bo drm_slp_bo_attach(drm_slp_bufmgr bufmgr,
+/* Functions for buffer mnager */
+drm_slp_bufmgr
+drm_slp_bufmgr_init(int fd, void * arg);
+void
+drm_slp_bufmgr_destroy(drm_slp_bufmgr bufmgr);
+int
+drm_slp_bufmgr_lock(drm_slp_bufmgr bufmgr);
+int
+drm_slp_bufmgr_unlock(drm_slp_bufmgr bufmgr);
+int
+drm_slp_bufmgr_cache_flush(drm_slp_bufmgr bufmgr, drm_slp_bo bo, int flags);
+
+
+/*Functions for bo*/
+int
+drm_slp_bo_size (drm_slp_bo bo);
+drm_slp_bo
+drm_slp_bo_ref(drm_slp_bo bo);
+void
+drm_slp_bo_unref(drm_slp_bo bo);
+drm_slp_bo
+drm_slp_bo_alloc(drm_slp_bufmgr bufmgr,
+                            const char* name,
+                            int size,
+                            int flags);
+drm_slp_bo
+drm_slp_bo_attach(drm_slp_bufmgr bufmgr,
                              const char*    name,
-                             void*          ptr,
-                             int            size,
-                             void*          native_handle);
-
-drm_slp_bo   drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key);
-unsigned int drm_slp_bo_export(drm_slp_bo bo);
-
-void*   drm_slp_bo_map(drm_slp_bo bo, int device, int opt);
-int     drm_slp_bo_unmap(drm_slp_bo bo, int device);
-
-int drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2);
-
-
+                             int type,
+                             int size,
+                             unsigned int handle);
+drm_slp_bo
+drm_slp_bo_import(drm_slp_bufmgr bufmgr, unsigned int key);
+unsigned int
+drm_slp_bo_export(drm_slp_bo bo);
+unsigned int
+drm_slp_bo_get_handle(drm_slp_bo, int device);
+unsigned int
+drm_slp_bo_map(drm_slp_bo bo, int device, int opt);
+int
+drm_slp_bo_unmap(drm_slp_bo bo, int device);
+int
+drm_slp_bo_swap(drm_slp_bo bo1, drm_slp_bo bo2);
+
+/*Functions for userdata of bo*/
 typedef void   (*drm_data_free)(void *);
-int drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func);
-int drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key);
-int drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data);
-int drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data);
-
+int
+drm_slp_bo_add_user_data(drm_slp_bo bo, unsigned long key, drm_data_free data_free_func);
+int
+drm_slp_bo_delete_user_data(drm_slp_bo bo, unsigned long key);
+int
+drm_slp_bo_set_user_data(drm_slp_bo bo, unsigned long key, void* data);
+int
+drm_slp_bo_get_user_data(drm_slp_bo bo, unsigned long key, void** data);
 #endif /* _DRM_SLP_BUFMGR_H_ */
diff --git a/slp/list.h b/slp/list.h
new file mode 100644 (file)
index 0000000..e967b93
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ *
+ * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND. USA.
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ */
+
+/**
+ * \file
+ * List macros heavily inspired by the Linux kernel
+ * list handling. No list looping yet.
+ *
+ * Is not threadsafe, so common operations need to
+ * be protected using an external mutex.
+ */
+#ifndef _U_DOUBLE_LIST_H_
+#define _U_DOUBLE_LIST_H_
+
+#include <stddef.h>
+
+static void list_inithead(struct list_head *item)
+{
+    item->prev = item;
+    item->next = item;
+}
+
+static inline void list_add(struct list_head *item, struct list_head *list)
+{
+    item->prev = list;
+    item->next = list->next;
+    list->next->prev = item;
+    list->next = item;
+}
+
+static inline void list_addtail(struct list_head *item, struct list_head *list)
+{
+    item->next = list;
+    item->prev = list->prev;
+    list->prev->next = item;
+    list->prev = item;
+}
+
+static inline void list_replace(struct list_head *from, struct list_head *to)
+{
+    to->prev = from->prev;
+    to->next = from->next;
+    from->next->prev = to;
+    from->prev->next = to;
+}
+
+static inline void list_del(struct list_head *item)
+{
+    item->prev->next = item->next;
+    item->next->prev = item->prev;
+}
+
+static inline void list_delinit(struct list_head *item)
+{
+    item->prev->next = item->next;
+    item->next->prev = item->prev;
+    item->next = item;
+    item->prev = item;
+}
+
+#define LIST_INITHEAD(__item) list_inithead(__item)
+#define LIST_ADD(__item, __list) list_add(__item, __list)
+#define LIST_ADDTAIL(__item, __list) list_addtail(__item, __list)
+#define LIST_REPLACE(__from, __to) list_replace(__from, __to)
+#define LIST_DEL(__item) list_del(__item)
+#define LIST_DELINIT(__item) list_delinit(__item)
+
+#define LIST_ENTRY(__type, __item, __field)   \
+    ((__type *)(((char *)(__item)) - offsetof(__type, __field)))
+
+#define LIST_IS_EMPTY(__list)                   \
+    ((__list)->next == (__list))
+
+#ifndef container_of
+#define container_of(ptr, sample, member)                              \
+    (void *)((char *)(ptr)                                             \
+            - ((char *)&(sample)->member - (char *)(sample)))
+#endif
+
+#define LIST_FOR_EACH_ENTRY(pos, head, member)                         \
+   for (pos = container_of((head)->next, pos, member);                 \
+       &pos->member != (head);                                         \
+       pos = container_of(pos->member.next, pos, member))
+
+#define LIST_FOR_EACH_ENTRY_SAFE(pos, storage, head, member)   \
+   for (pos = container_of((head)->next, pos, member),                 \
+       storage = container_of(pos->member.next, pos, member);  \
+       &pos->member != (head);                                         \
+       pos = storage, storage = container_of(storage->member.next, storage, member))
+
+#define LIST_FOR_EACH_ENTRY_SAFE_REV(pos, storage, head, member)       \
+   for (pos = container_of((head)->prev, pos, member),                 \
+       storage = container_of(pos->member.prev, pos, member);          \
+       &pos->member != (head);                                         \
+       pos = storage, storage = container_of(storage->member.prev, storage, member))
+
+#define LIST_FOR_EACH_ENTRY_FROM(pos, start, head, member)             \
+   for (pos = container_of((start), pos, member);                      \
+       &pos->member != (head);                                         \
+       pos = container_of(pos->member.next, pos, member))
+
+#define LIST_FOR_EACH_ENTRY_FROM_REV(pos, start, head, member)         \
+   for (pos = container_of((start), pos, member);                      \
+       &pos->member != (head);                                         \
+       pos = container_of(pos->member.prev, pos, member))
+
+#endif /*_U_DOUBLE_LIST_H_*/
index 0851262..0d539fb 100644 (file)
@@ -10,13 +10,16 @@ check_PROGRAMS = \
        dristat \
        drmstat
 
-SUBDIRS = modeprint
+SUBDIRS = modeprint proptest
 
 if HAVE_LIBKMS
-SUBDIRS += kmstest modetest planetest
+SUBDIRS += kmstest modetest
 endif
 
+SUBDIRS += ipptest
+SUBDIRS += rottest
 SUBDIRS += gemtest
+SUBDIRS += g2dtest
 
 if HAVE_RADEON
 SUBDIRS += radeon
similarity index 61%
rename from tests/planetest/Makefile.am
rename to tests/g2dtest/Makefile.am
index bc94ed4..fc24856 100644 (file)
@@ -1,15 +1,18 @@
 AM_CFLAGS = \
        -I$(top_srcdir)/include/drm \
        -I$(top_srcdir)/libkms/ \
+       -I$(top_srcdir)/exynos/ \
        -I$(top_srcdir) \
        $(CAIRO_CFLAGS)
 
 noinst_PROGRAMS = \
-       planetest
+       g2dtest
 
-planetest_SOURCES = \
-       planetest.c
-planetest_LDADD = \
+g2dtest_SOURCES = \
+       g2dtest.c
+
+g2dtest_LDADD = \
        $(top_builddir)/libdrm.la \
        $(top_builddir)/libkms/libkms.la \
+       $(top_builddir)/exynos/libdrm_exynos.la \
        $(CAIRO_LIBS)
diff --git a/tests/g2dtest/g2d.h b/tests/g2dtest/g2d.h
new file mode 100644 (file)
index 0000000..1a62880
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _G2D_H_
+#define _G2D_H_
+
+#include "g2d_reg.h"
+
+typedef enum {
+       G2D_SELECT_MODE_NORMAL = (0 << 0),
+       G2D_SELECT_MODE_FGCOLOR = (1 << 0),
+       G2D_SELECT_MODE_BGCOLOR = (2 << 0),
+       G2D_SELECT_MODE_MAX = (3 << 0),
+} G2dSelectMode;
+
+typedef enum {
+       /* COLOR FORMAT */
+       G2D_COLOR_FMT_XRGB8888,
+       G2D_COLOR_FMT_ARGB8888,
+       G2D_COLOR_FMT_RGB565,
+       G2D_COLOR_FMT_XRGB1555,
+       G2D_COLOR_FMT_ARGB1555,
+       G2D_COLOR_FMT_XRGB4444,
+       G2D_COLOR_FMT_ARGB4444,
+       G2D_COLOR_FMT_PRGB888,
+       G2D_COLOR_FMT_YCbCr444,
+       G2D_COLOR_FMT_YCbCr422,
+       G2D_COLOR_FMT_YCbCr420 = 10,
+       G2D_COLOR_FMT_A8,                       /* alpha 8bit */
+       G2D_COLOR_FMT_L8,                       /* Luminance 8bit: gray color */
+       G2D_COLOR_FMT_A1,                       /* alpha 1bit */
+       G2D_COLOR_FMT_A4,                       /* alpha 4bit */
+       G2D_COLOR_FMT_MASK = (15 << 0),         /* VER4.1 */
+
+       /* COLOR ORDER */
+       G2D_ORDER_AXRGB = (0 << 4),                     /* VER4.1 */
+       G2D_ORDER_RGBAX = (1 << 4),                     /* VER4.1 */
+       G2D_ORDER_AXBGR = (2 << 4),                     /* VER4.1 */
+       G2D_ORDER_BGRAX = (3 << 4),                     /* VER4.1 */
+       G2D_ORDER_MASK = (3 << 4),                      /* VER4.1 */
+
+       /* Number of YCbCr plane */
+       G2D_YCbCr_1PLANE = (0 << 8),                    /* VER4.1 */
+       G2D_YCbCr_2PLANE = (1 << 8),                    /* VER4.1 */
+       G2D_YCbCr_PLANE_MASK = (3 << 8),                /* VER4.1 */
+
+       /* Order in YCbCr */
+       G2D_YCbCr_ORDER_CrY1CbY0 = (0 << 12),           /* VER4.1 */
+       G2D_YCbCr_ORDER_CbY1CrY0 = (1 << 12),           /* VER4.1 */
+       G2D_YCbCr_ORDER_Y1CrY0Cb = (2 << 12),           /* VER4.1 */
+       G2D_YCbCr_ORDER_Y1CbY0Cr = (3 << 12),           /* VER4.1 */
+       G2D_YCbCr_ORDER_MASK = (3 < 12),                /* VER4.1 */
+
+       /* CSC */
+       G2D_CSC_601 = (0 << 16),                        /* VER4.1 */
+       G2D_CSC_709 = (1 << 16),                        /* VER4.1 */
+       G2D_CSC_MASK = (1 << 16),                       /* VER4.1 */
+
+       /* Valid value range of YCbCr */
+       G2D_YCbCr_RANGE_NARROW = (0 << 17),             /* VER4.1 */
+       G2D_YCbCr_RANGE_WIDE = (1 << 17),               /* VER4.1 */
+       G2D_YCbCr_RANGE_MASK= (1 << 17),                /* VER4.1 */
+
+       G2D_COLOR_MODE_MASK = 0xFFFFFFFF
+} G2dColorMode;
+
+#endif /* _G2D_H_ */
diff --git a/tests/g2dtest/g2d_reg.h b/tests/g2dtest/g2d_reg.h
new file mode 100644 (file)
index 0000000..b991681
--- /dev/null
@@ -0,0 +1,108 @@
+#ifndef _G2D_REG_H_
+#define _G2D_REG_H_
+
+/* Registers */
+/* GEBERAL REGISTER */
+#define SOFT_RESET_REG                 (0x0000)
+#define INTEN_REG                      (0x0004)
+#define INTC_PEND_REG                  (0x000c)
+#define FIFO_STAT_REG                  (0x0010)
+#define AXI_MODE_REG                   (0x001C)
+#define DMA_SFR_BASE_ADDR_REG          (0x0080)
+#define DMA_COMMAND_REG                        (0x0084)
+#define DMA_EXE_LIST_NUM_REG           (0x0088)
+#define DMA_STATUS_REG                 (0x008C)
+#define DMA_HOLD_CMD_REG               (0x0090)
+
+/* COMMAND REGISTER */
+#define BITBLT_START_REG               (0x0100)
+#define BITBLT_COMMAND_REG             (0x0104)
+#define BLEND_FUNCTION_REG             (0x0108)        /* VER4.1 */
+#define ROUND_MODE_REG                 (0x010C)        /* VER4.1 */
+
+/* PARAMETER SETTING REGISTER */
+
+/*     ROTATE and DIRECTION    */
+#define ROTATE_REG                     (0x0200)
+#define SRC_MASK_DIRECT_REG            (0x0204)
+#define DST_PAT_DIRECT_REG             (0x0208)
+
+/*     SOURCE  */
+#define SRC_SELECT_REG                 (0x0300)
+#define SRC_BASE_ADDR_REG              (0x0304)
+#define SRC_STRIDE_REG                 (0x0308)
+#define SRC_COLOR_MODE_REG             (0x030c)
+#define SRC_LEFT_TOP_REG               (0x0310)
+#define SRC_RIGHT_BOTTOM_REG           (0x0314)
+#define SRC_PLANE2_BASE_ADDR_REG       (0x0318)        /* VER4.1 */
+#define SRC_REPEAT_MODE_REG            (0x031C)
+#define SRC_PAD_VALUE_REG              (0x0320)
+#define SRC_A8_RGB_EXT_REG             (0x0324)
+#define SRC_SCALE_CTRL_REG             (0x0328)
+#define SRC_XSCALE_REG                 (0x032C)
+#define SRC_YSCALE_REG                 (0x0330)
+
+/*     DESTINATION     */
+#define DST_SELECT_REG                 (0x0400)
+#define DST_BASE_ADDR_REG              (0x0404)
+#define DST_STRIDE_REG                 (0x0408)
+#define DST_COLOR_MODE_REG             (0x040C)
+#define DST_LEFT_TOP_REG               (0x0410)
+#define DST_RIGHT_BOTTOM_REG           (0x0414)
+#define DST_PLANE2_BASE_ADDR_REG       (0x0418)        /* VER4.1 */
+#define DST_A8_RGB_EXT_REG             (0x041C)
+
+/*     PATTERN */
+#define PAT_BASE_ADDR_REG              (0x0500)
+#define PAT_SIZE_REG                   (0x0504)
+#define PAT_COLOR_MODE_REG             (0x0508)
+#define PAT_OFFSET_REG                 (0x050C)
+#define PAT_STRIDE_REG                 (0x0510)
+
+/*     MASK    */
+#define MASK_BASE_ADDR_REG             (0x0520)
+#define MASK_STRIDE_REG                        (0x0524)
+#define MASK_LEFT_TOP_REG              (0x0528)        /* VER4.1 */
+#define MASK_RIGHT_BOTTOM_REG          (0x052C)        /* VER4.1 */
+#define MASK_MODE_REG                  (0x0530)        /* VER4.1 */
+#define MASK_REPEAT_MODE_REG           (0x0534)
+#define MASK_PAD_VALUE_REG             (0x0538)
+#define MASK_SCALE_CTRL_REG            (0x053C)
+#define MASK_XSCALE_REG                        (0x0540)
+#define MASK_YSCALE_REG                        (0x0544)
+
+/* CLIPPING WINDOW */
+#define CW_LT_REG                      (0x0600)
+#define CW_RB_REG                      (0x0604)
+
+/* ROP & ALPHA SETTING */
+#define THIRD_OPERAND_REG              (0x0610)
+#define ROP4_REG                       (0x0614)
+#define ALPHA_REG                      (0x0618)
+
+/* COLOR SETTING */
+#define FG_COLOR_REG                   (0x0700)
+#define BG_COLOR_REG                   (0x0704)
+#define BS_COLOR_REG                   (0x0708)
+#define SF_COLOR_REG                   (0x070C)        /* VER4.1 */
+
+/* COLOR KEY */
+#define SRC_COLORKEY_CTRL_REG          (0x0710)
+#define SRC_COLORKEY_DR_MIN_REG                (0x0714)
+#define SRC_COLORKEY_DR_MAX_REG                (0x0718)
+#define DST_COLORKEY_CTRL_REG          (0x071C)
+#define DST_COLORKEY_DR_MIN_REG                (0x0720)
+#define DST_COLORKEY_DR_MAX_REG                (0x0724)
+/*     YCbCr src Color Key     */
+#define YCbCr_SRC_COLORKEY_CTRL_REG    (0x0728)        /* VER4.1 */
+#define YCbCr_SRC_COLORKEY_DR_MIN_REG  (0x072C)        /* VER4.1 */
+#define YCbCr_SRC_COLORKEY_DR_MAX_REG  (0x0730)        /* VER4.1 */
+/*     YCbCr dst Color Key     */
+#define YCbCr_DST_COLORKEY_CTRL_REG    (0x0734)        /* VER4.1 */
+#define YCbCr_DST_COLORKEY_DR_MIN_REG  (0x0738)        /* VER4.1 */
+#define YCbCr_DST_COLORKEY_DR_MAX_REG  (0x073C)        /* VER4.1 */
+
+/* bits of BITBLT_COMMAND_REG */
+#define        G2D_FAST_SOLID_COLOR_FILL       (1 << 28)
+
+#endif /* _G2D_REG_H_ */
diff --git a/tests/g2dtest/g2dtest.c b/tests/g2dtest/g2dtest.c
new file mode 100644 (file)
index 0000000..7fa2176
--- /dev/null
@@ -0,0 +1,593 @@
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "exynos_drm.h"
+#include "drm_fourcc.h"
+#include "g2d.h"
+
+#define DRM_MODULE_NAME                "exynos"
+
+struct connector {
+       uint32_t id;
+       char mode_str[64];
+       drmModeModeInfo *mode;
+       drmModeEncoder *encoder;
+       int crtc;
+       int plane_zpos;
+       unsigned int fb_id[2], current_fb_id;
+       struct timeval start;
+
+       int swap_count;
+};
+
+struct drm_buffer {
+       struct drm_exynos_gem_create    gem;
+       struct drm_exynos_gem_mmap      gem_mmap;
+};
+
+struct drm_fb {
+       uint32_t                        id;
+       struct drm_buffer               drm_buffer;
+};
+
+struct drm_desc {
+       int                             fd;
+       struct connector                connector;
+       int                             plane_id[5];
+       int                             width;
+       int                             height;
+};
+
+enum format {
+       FMT_RGB565,
+       FMT_RGB888,
+       FMT_NV12M,
+};
+
+static void connector_find_mode(int fd, struct connector *c,
+                               drmModeRes *resources)
+{
+       drmModeConnector *connector;
+       int i, j;
+
+       /* First, find the connector & mode */
+       c->mode = NULL;
+       for (i = 0; i < resources->count_connectors; i++) {
+               connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+               if (!connector) {
+                       fprintf(stderr, "could not get connector %i: %s\n",
+                               resources->connectors[i], strerror(errno));
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (!connector->count_modes) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (connector->connector_id != c->id) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               for (j = 0; j < connector->count_modes; j++) {
+                       c->mode = &connector->modes[j];
+                       if (!strcmp(c->mode->name, c->mode_str))
+                               break;
+               }
+
+               /* Found it, break out */
+               if (c->mode)
+                       break;
+
+               drmModeFreeConnector(connector);
+       }
+
+       if (!c->mode) {
+               fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
+               return;
+       }
+
+       /* Now get the encoder */
+       for (i = 0; i < resources->count_encoders; i++) {
+               c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+               if (!c->encoder) {
+                       fprintf(stderr, "could not get encoder %i: %s\n",
+                               resources->encoders[i], strerror(errno));
+                       drmModeFreeEncoder(c->encoder);
+                       continue;
+               }
+
+               if (c->encoder->encoder_id  == connector->encoder_id)
+                       break;
+
+               drmModeFreeEncoder(c->encoder);
+       }
+
+       if (c->crtc == -1)
+               c->crtc = c->encoder->crtc_id;
+}
+
+static int connector_find_plane(int fd, unsigned int *plane_id)
+{
+       drmModePlaneRes *plane_resources;
+       drmModePlane *ovr;
+       int i;
+
+       plane_resources = drmModeGetPlaneResources(fd);
+       if (!plane_resources) {
+               fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
+                       strerror(errno));
+               return -1;
+       }
+
+       for (i = 0; i < plane_resources->count_planes; i++) {
+               plane_id[i] = 0;
+
+               ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
+               if (!ovr) {
+                       fprintf(stderr, "drmModeGetPlane failed: %s\n",
+                               strerror(errno));
+                       continue;
+               }
+
+               if (ovr->possible_crtcs & (1 << 0))
+                       plane_id[i] = ovr->plane_id;
+               drmModeFreePlane(ovr);
+       }
+
+       return 0;
+}
+
+static int exynos_g2d_get_ver(int fd, struct drm_exynos_g2d_get_ver *ver)
+{
+       int ret;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_GET_VER, ver);
+       if (ret < 0) {
+               fprintf(stderr, "failed to get version: %s\n", strerror(-ret));
+               return ret;
+       }
+
+       return 0;
+}
+
+static int exynos_g2d_set_cmdlist(int fd,
+                                 struct drm_exynos_g2d_set_cmdlist *cmdlist)
+{
+       int ret;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_SET_CMDLIST, cmdlist);
+       if (ret < 0) {
+               fprintf(stderr, "failed to set cmdlist: %s\n", strerror(-ret));
+               return ret;
+       }
+
+       return 0;
+}
+
+static int exynos_g2d_exec(int fd, int async)
+{
+       struct drm_exynos_g2d_exec exec;
+       int ret;
+
+       exec.async = async;
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_G2D_EXEC, &exec);
+       if (ret < 0) {
+               fprintf(stderr, "failed to execute: %s\n", strerror(-ret));
+               return ret;
+       }
+
+       return 0;
+}
+
+static int exynos_gem_create(int fd, struct drm_exynos_gem_create *gem)
+{
+       int ret;
+
+       if (!gem)
+               return -EINVAL;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CREATE, gem);
+       if (ret < 0)
+               perror("ioctl failed\n");
+
+       return ret;
+}
+
+static int exynos_gem_map_offset(int fd, struct drm_exynos_gem_map_off *map_off)
+{
+       int ret;
+
+       if (!map_off)
+               return -EINVAL;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_MAP_OFFSET, map_off);
+       if (ret < 0)
+               perror("ioctl failed\n");
+
+       return ret;
+}
+
+static int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap)
+{
+       int ret;
+
+       if (!in_mmap)
+               return -EINVAL;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_MMAP, in_mmap);
+       if (ret < 0)
+               perror("ioctl failed\n");
+
+       return ret;
+}
+
+static int exynos_gem_close(int fd, struct drm_gem_close *gem_close)
+{
+       int ret;
+
+       if (!gem_close)
+               return -EINVAL;
+
+       ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, gem_close);
+       if (ret < 0)
+               perror("ioctl failed\n");
+
+       return ret;
+}
+
+static struct drm_desc *drm_alloc_desc(void)
+{
+       struct drm_desc *drm_desc;
+
+       drm_desc = malloc(sizeof(struct drm_desc));
+       if (!drm_desc) {
+               perror("memory alloc error\n");
+               return NULL;
+       }
+       memset(drm_desc, 0, sizeof(struct drm_desc));
+
+       return drm_desc;
+}
+
+static int drm_open(struct drm_desc *drm_desc)
+{
+       if (!drm_desc) {
+               fprintf(stderr, "drm_desc is NULL\n");
+               return -EINVAL;
+       }
+
+       drm_desc->fd = drmOpen(DRM_MODULE_NAME, NULL);
+       if (drm_desc->fd < 0) {
+               printf("Failed to open %s module\n", DRM_MODULE_NAME);
+               return drm_desc->fd;
+       }
+
+       return 0;
+}
+
+static int drm_create_buffer(struct drm_desc *drm_desc, struct drm_fb *drm_fb,
+                            int width, int height)
+{
+       struct drm_buffer *drm_buffer;
+       unsigned int num_planes;
+       unsigned long size;
+       int i;
+       int ret;
+
+       if (!drm_desc)
+               return -EINVAL;
+
+       size = width * height * 4;
+
+       drm_buffer = &drm_fb->drm_buffer;
+
+       {
+               struct drm_exynos_gem_create *gem = &drm_buffer->gem;
+               struct drm_exynos_gem_mmap *gem_mmap = &drm_buffer->gem_mmap;
+
+               memset(gem, 0, sizeof(struct drm_exynos_gem_create));
+               gem->size = size;
+
+               ret = exynos_gem_create(drm_desc->fd, gem);
+               if (ret < 0) {
+                       printf("failed to create gem\n");
+                       goto err_gem;
+               }
+
+               gem_mmap->handle = gem->handle;
+               gem_mmap->size = gem->size;
+               ret = exynos_gem_mmap(drm_desc->fd, gem_mmap);
+               if (ret < 0) {
+                       printf("failed to mmap gem directly\n");
+                       goto err_gem;
+               }
+
+               /* init gem buffer */
+               memset((void *)(unsigned long)gem_mmap->mapped, 0,
+                               gem_mmap->size);
+       }
+
+       return 0;
+
+err_gem:
+       {
+               struct drm_exynos_gem_create *gem = &drm_buffer->gem;
+               struct drm_gem_close gem_close;
+
+               gem_close.handle = gem->handle;
+               exynos_gem_close(drm_desc->fd, &gem_close);
+       }
+
+       return ret;
+}
+
+static int drm_create_fb(struct drm_desc *drm_desc, struct drm_fb *drm_fb,
+                        int width, int height)
+{
+       unsigned int pixel_format;
+       unsigned int num_planes;
+       unsigned int pitch;
+       int i;
+       int j;
+       int ret;
+
+       if (!drm_desc)
+               return -EINVAL;
+
+       drm_desc->width = width;
+       drm_desc->height = height;
+
+       pixel_format = DRM_FORMAT_RGBA8888;
+       num_planes = 1;
+       pitch = width * 4;
+
+       {
+               uint32_t bo[4] = {0,};
+               uint32_t pitches[4] = {0,};
+               uint32_t offset[4] = {0,};
+
+               ret = drm_create_buffer(drm_desc, drm_fb, width, height);
+               if (ret < 0)
+                       goto err;
+
+               for (j = 0; j < num_planes; j++) {
+                       struct drm_buffer *drm_buffer = &drm_fb->drm_buffer;
+                       struct drm_exynos_gem_create *gem = &drm_buffer->gem;
+
+                       bo[j] = gem->handle;
+                       pitches[j] = pitch;
+               }
+
+               ret = drmModeAddFB2(drm_desc->fd, width, height, pixel_format,
+                               bo, pitches, offset, &drm_fb->id,
+                               0);
+               if (ret < 0) {
+                       perror("failed to add fb\n");
+                       goto err;
+               }
+       }
+
+       return 0;
+
+err:
+       /* TODO: free buffer */
+       return ret;
+}
+
+static int drm_set_crtc(struct drm_desc *drm_desc, struct connector *c,
+                       struct drm_fb *drm_fb)
+{
+       drmModeRes *resources;
+       int ret;
+
+       memcpy(&drm_desc->connector, c, sizeof(struct connector));
+
+       resources = drmModeGetResources(drm_desc->fd);
+       if (!resources) {
+               fprintf(stderr, "drmModeGetResources failed: %s\n",
+                       strerror(errno));
+               ret = -EFAULT;
+               goto err;
+       }
+
+       connector_find_mode(drm_desc->fd, &drm_desc->connector, resources);
+       drmModeFreeResources(resources);
+
+       ret = drmModeSetCrtc(drm_desc->fd, drm_desc->connector.crtc,
+                       drm_fb->id, 0, 0,
+                       &drm_desc->connector.id, 1,
+                       drm_desc->connector.mode);
+       if (ret) {
+               fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
+               goto err;
+       }
+
+       return 0;
+
+err:
+       /* TODO */
+       return ret;
+}
+
+static inline void set_cmd(struct drm_exynos_g2d_cmd *cmd,
+                                     __u32 offset, __u32 data)
+{
+       cmd->offset = offset;
+       cmd->data = data;
+}
+
+static int exynos_g2d_test_solid_fill(struct drm_desc *drm_desc, int x, int y,
+                                     int color, int gem_handle)
+{
+       struct drm_exynos_g2d_set_cmdlist cmdlist;
+       struct drm_exynos_g2d_cmd cmd[20];
+       struct drm_exynos_g2d_cmd cmd_gem[5];
+       int nr = 0;
+       int gem_nr = 0;
+       int ret;
+
+       memset(&cmdlist, 0, sizeof(struct drm_exynos_g2d_set_cmdlist));
+       memset(cmd, 0, sizeof(struct drm_exynos_g2d_cmd) * 20);
+       memset(cmd_gem, 0, sizeof(struct drm_exynos_g2d_cmd) * 5);
+
+       cmdlist.cmd = cmd;
+       cmdlist.cmd_gem = cmd_gem;
+
+       set_cmd(&cmd[nr++], BITBLT_COMMAND_REG, G2D_FAST_SOLID_COLOR_FILL);
+       /* [14:10] R, [9:5] G, [4:0] B */
+       set_cmd(&cmd[nr++], SF_COLOR_REG, color);
+
+       /* DST */
+       set_cmd(&cmd[nr++], DST_SELECT_REG, G2D_SELECT_MODE_FGCOLOR);
+       set_cmd(&cmd_gem[gem_nr++], DST_BASE_ADDR_REG, gem_handle);
+       set_cmd(&cmd[nr++], DST_STRIDE_REG, 720 * 4);
+       set_cmd(&cmd[nr++], DST_COLOR_MODE_REG, G2D_COLOR_FMT_ARGB8888 |
+                                               G2D_ORDER_AXRGB);
+       set_cmd(&cmd[nr++], DST_LEFT_TOP_REG, (0 << 16) | 0);
+       set_cmd(&cmd[nr++], DST_RIGHT_BOTTOM_REG, (y << 16) | x);
+       set_cmd(&cmd[nr++], DST_A8_RGB_EXT_REG, 0);
+
+       cmdlist.cmd_nr = nr;
+       cmdlist.cmd_gem_nr = gem_nr;
+
+       cmdlist.event_type = G2D_EVENT_NONSTOP;
+       cmdlist.user_data = 1234;
+
+       ret = exynos_g2d_set_cmdlist(drm_desc->fd, &cmdlist);
+       if (ret < 0)
+               return ret;
+}
+
+static int exynos_g2d_event(int fd)
+{
+       char buffer[1024];
+       int len, i;
+       struct drm_event *e;
+       struct drm_exynos_g2d_event *g2d_event;
+
+       len = read(fd, buffer, sizeof buffer);
+       if (len == 0)
+               return 0;
+       if (len < sizeof *e)
+               return -1;
+
+       i = 0;
+       while (i < len) {
+               e = (struct drm_event *) &buffer[i];
+               switch (e->type) {
+               case DRM_EXYNOS_G2D_EVENT:
+                       g2d_event = (struct drm_exynos_g2d_event *) e;
+                       printf("cmdlist_no: %d\n", g2d_event->cmdlist_no);
+                       printf("user_data: %lld\n", g2d_event->user_data);
+                       break;
+               default:
+                       break;
+               }
+               i += e->length;
+       }
+
+       return 0;
+}
+
+int main(int argc, char **argv)
+{
+       struct connector con_args;
+       struct drm_desc *drm_desc;
+       struct drm_fb drm_fb;
+       struct drm_exynos_g2d_get_ver ver;
+       int x, y;
+       int ret;
+
+       /* default set of connector */
+       memset(&con_args, 0, sizeof(struct connector));
+       con_args.id = 12;
+       con_args.crtc = 3;
+       con_args.plane_zpos = -1;
+       strcpy(con_args.mode_str, "720x1280");
+       x = 720;
+       y = 1280;
+
+       drm_desc = drm_alloc_desc();
+       if (!drm_desc) {
+               ret = -1;
+               goto err_free;
+       }
+
+       ret = drm_open(drm_desc);
+       if (ret < 0)
+               goto err_free;
+
+       /* check version */
+       ret = exynos_g2d_get_ver(drm_desc->fd, &ver);
+       if (ret < 0)
+               return ret;
+
+       if (ver.major != 4 || ver.minor != 1) {
+               fprintf(stderr, "version(%d.%d) mismatch\n", ver.major, ver.minor);
+               return -1;
+       }
+       printf("g2d hw version: %d.%d\n", ver.major, ver.minor);
+
+       ret = drm_create_fb(drm_desc, &drm_fb, x, y);
+       if (ret < 0)
+               goto err_drm_close;
+
+       ret = drm_set_crtc(drm_desc, &con_args, &drm_fb);
+       if (ret < 0)
+               goto err;
+
+       getchar();
+
+       ret = exynos_g2d_test_solid_fill(drm_desc, x, y, 0x1f,
+                                        drm_fb.drm_buffer.gem.handle);
+       if (ret < 0)
+               goto err;
+
+       ret = exynos_g2d_exec(drm_desc->fd, 1);
+       if (ret < 0)
+               return ret;
+
+       while (1) {
+               struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+               fd_set fds;
+               int ret;
+
+               FD_ZERO(&fds);
+               FD_SET(0, &fds);
+               FD_SET(drm_desc->fd, &fds);
+               ret = select(drm_desc->fd + 1, &fds, NULL, NULL, &timeout);
+
+               if (ret <= 0) {
+                       fprintf(stderr, "select timed out or error (ret %d)\n",
+                               ret);
+                       continue;
+               } else if (FD_ISSET(0, &fds)) {
+                       break;
+               }
+
+               exynos_g2d_event(drm_desc->fd);
+       }
+
+       getchar();
+
+       /* TODO */
+
+err:
+       /* TODO */
+err_drm_close:
+       drmClose(drm_desc->fd);
+err_free:
+       if (drm_desc)
+               free(drm_desc);
+
+       return ret;
+}
index 8dc8832..ce43e42 100644 (file)
@@ -117,10 +117,15 @@ int main(int argc, char **argv)
 {
        int fd;
 
+       if (geteuid()) {
+               fprintf(stderr, "requires root privileges, skipping\n");
+               return 77;
+       }
+
        fd = drm_open_matching("8086:*", 0);
        if (fd < 0) {
                fprintf(stderr, "failed to open intel drm device, skipping\n");
-               return 0;
+               return 77;
        }
 
        test_flink(fd);
index 08432a1..eb46c07 100644 (file)
@@ -1,5 +1,7 @@
 AM_CFLAGS = \
        -I$(top_srcdir)/include/drm \
+       -I$(top_srcdir)/libkms/ \
+       -I$(top_srcdir)/exynos/ \
        -I$(top_srcdir) \
        $(CAIRO_CFLAGS)
 
@@ -8,6 +10,9 @@ noinst_PROGRAMS = \
 
 gemtest_SOURCES = \
        gemtest.c
+
 gemtest_LDADD = \
        $(top_builddir)/libdrm.la \
+       $(top_builddir)/libkms/libkms.la \
+       $(top_builddir)/exynos/libdrm_exynos.la \
        $(CAIRO_LIBS)
index f7f0e70..018f83d 100644 (file)
 #include <stdint.h>
 #include <unistd.h>
 #include <string.h>
+#include <fcntl.h>
 #include <errno.h>
+#include <sys/ioctl.h>
 #include <sys/poll.h>
 #include <sys/time.h>
 #include <sys/mman.h>
 
 #include "xf86drm.h"
 #include "xf86drmMode.h"
+#include "libkms.h"
+
 #include "exynos_drm.h"
+#include "exynos_drmif.h"
+
+#include "ump_ref_drv.h"
 
 #ifdef HAVE_CAIRO
 #include <math.h>
@@ -60,6 +67,8 @@
 #endif
 
 #define ALIGN(x, a) (((x) + (a) - 1) & ~((a) + 1))
+#define DEFAULT_SIZE   (1280 * 720 * 4)
+#define MAX_CMD                5
 
 /*
  * DIRECT_MAP:
 #define DIRECT_MAP
 //#define INDIRECT_MAP
 
-#define CACHE_TEST
+#if 0
+#define UMP_TEST
+
+#define GET_PHY_TEST
+
+#define VIDI_TEST
+
+#define GEMGET_TEST
+#endif
+
+enum exynos_test_type {
+       CMD_ALLOC               = 1 << 0,
+       CMD_CACHE               = 1 << 1,
+       CMD_PRIME               = 1 << 2,
+       CMD_UMP                 = 1 << 3,
+
+       ALLOC_CONTIG            = 1 << 4,
+       ALLOC_NONCONTIG         = 1 << 5,
+       ALLOC_USERPTR           = 1 << 6,
+
+       ALLOC_MAP_C             = 1 << 7,
+       ALLOC_MAP_NC            = 1 << 8,
+       ALLOC_MAP_WC            = 1 << 9,
+
+       CACHE_L1                = 1 << 10,
+       CACHE_L2                = 1 << 11,
+       CACHE_ALL_CORES         = 1 << 12,
+       CACHE_ALL_CACHES        = CACHE_L1 | CACHE_L2,
+       CACHE_ALL_CACHES_CORES  = CACHE_ALL_CACHES | CACHE_ALL_CORES,
+
+       CACHE_CLEAN_ALL         = 0 << 13,
+       CACHE_INV_ALL           = 0 << 14,
+       CACHE_FLUSH_ALL         = CACHE_CLEAN_ALL | CACHE_INV_ALL,
+
+       CACHE_CLEAN_RANGE       = 1 << 13,
+       CACHE_INV_RANGE         = 1 << 14,
+       CACHE_FLUSH_RANGE       = CACHE_CLEAN_RANGE | CACHE_INV_RANGE,
+
+       DMABUF_IMPORT           = 1 << 15,
+       DMABUF_EXPORT           = 1 << 16,
+       DMABUF_ALL              = DMABUF_IMPORT | DMABUF_EXPORT
+};
+
+struct exynos_gem_test {
+       char            *scmd[MAX_CMD];
+
+       unsigned int    cmd_type;
+       unsigned int    mem_type;
+       unsigned int    map_type;
+       unsigned int    cache_type;
+       unsigned int    cache_op_type;
+       unsigned long   start_offset;
+       unsigned long   end_offset;
+       unsigned int    dmabuf_type;
+};
+
+struct exynos_gem_test exynos_test;
 
 drmModeRes *resources;
 int fd, modes;
@@ -134,6 +199,7 @@ struct type_name connector_type_names[] = {
        { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
        { DRM_MODE_CONNECTOR_TV, "TV" },
        { DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
+       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
 };
 
 type_name_fn(connector_type)
@@ -289,6 +355,19 @@ void dump_framebuffers(void)
        printf("\n");
 }
 
+void exynos_test_dump(void)
+{
+
+       printf("cmd_type = %d\n", exynos_test.cmd_type);
+       printf("mem_type = %d\n", exynos_test.mem_type);
+       printf("map_type = %d\n", exynos_test.map_type);
+       printf("cache_type = %d\n", exynos_test.cache_type);
+       printf("cache_type = %d\n", exynos_test.cache_op_type);
+       printf("start_offset = 0x%lx\n", exynos_test.start_offset);
+       printf("end_offset = 0x%lx\n", exynos_test.end_offset);
+       printf("dmabuf_type = %d\n", exynos_test.dmabuf_type);
+}
+
 /*
  * Mode setting with the kernel interfaces is a bit of a chore.
  * First you have to find the connector in question and make sure the
@@ -375,6 +454,40 @@ connector_find_mode(struct connector *c)
                c->crtc = c->encoder->crtc_id;
 }
 
+static struct kms_bo *
+allocate_buffer(struct kms_driver *kms,
+               int width, int height, int *stride)
+{
+       struct kms_bo *bo;
+       unsigned bo_attribs[] = {
+               KMS_WIDTH,   0,
+               KMS_HEIGHT,  0,
+               KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
+               KMS_TERMINATE_PROP_LIST
+       };
+       int ret;
+
+       bo_attribs[1] = width;
+       bo_attribs[3] = height;
+
+       ret = kms_bo_create(kms, bo_attribs, &bo);
+       if (ret) {
+               fprintf(stderr, "failed to alloc buffer: %s\n",
+                       strerror(-ret));
+               return NULL;
+       }
+
+       ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
+       if (ret) {
+               fprintf(stderr, "failed to retreive buffer stride: %s\n",
+                       strerror(-ret));
+               kms_bo_destroy(&bo);
+               return NULL;
+       }
+
+       return bo;
+}
+
 static void
 make_pwetty(void *data, int width, int height, int stride)
 {
@@ -421,6 +534,78 @@ make_pwetty(void *data, int width, int height, int stride)
 #endif
 }
 
+static int
+create_test_buffer(struct kms_driver *kms,
+                  int width, int height, int *stride_out,
+                  struct kms_bo **bo_out)
+{
+       struct kms_bo *bo;
+       int ret, i, j, stride;
+       void *virtual;
+
+       bo = allocate_buffer(kms, width, height, &stride);
+       if (!bo)
+               return -1;
+
+       ret = kms_bo_map(bo, &virtual);
+       if (ret) {
+               fprintf(stderr, "failed to map buffer: %s\n",
+                       strerror(-ret));
+               kms_bo_destroy(&bo);
+               return -1;
+       }
+
+       /* paint the buffer with colored tiles */
+       for (j = 0; j < height; j++) {
+               uint32_t *fb_ptr = (uint32_t*)((char*)virtual + j * stride);
+               for (i = 0; i < width; i++) {
+                       div_t d = div(i, width);
+                       fb_ptr[i] =
+                               0x00130502 * (d.quot >> 6) +
+                               0x000a1120 * (d.rem >> 6);
+               }
+       }
+
+       make_pwetty(virtual, width, height, stride);
+
+       kms_bo_unmap(bo);
+
+       *bo_out = bo;
+       *stride_out = stride;
+       return 0;
+}
+
+static int
+create_grey_buffer(struct kms_driver *kms,
+                  int width, int height, int *stride_out,
+                  struct kms_bo **bo_out)
+{
+       struct kms_bo *bo;
+       int size, ret, stride;
+       void *virtual;
+
+       bo = allocate_buffer(kms, width, height, &stride);
+       if (!bo)
+               return -1;
+
+       ret = kms_bo_map(bo, &virtual);
+       if (ret) {
+               fprintf(stderr, "failed to map buffer: %s\n",
+                       strerror(-ret));
+               kms_bo_destroy(&bo);
+               return -1;
+       }
+
+       size = stride * height;
+       memset(virtual, 0x77, size);
+       kms_bo_unmap(bo);
+
+       *bo_out = bo;
+       *stride_out = stride;
+
+       return 0;
+}
+
 void
 page_flip_handler(int fd, unsigned int frame,
                  unsigned int sec, unsigned int usec, void *data)
@@ -435,7 +620,7 @@ page_flip_handler(int fd, unsigned int frame,
                new_fb_id = c->fb_id[1];
        else
                new_fb_id = c->fb_id[0];
-                       
+
        drmModePageFlip(fd, c->crtc, new_fb_id,
                        DRM_MODE_PAGE_FLIP_EVENT, c);
        c->current_fb_id = new_fb_id;
@@ -450,25 +635,6 @@ page_flip_handler(int fd, unsigned int frame,
        }
 }
 
-static int exynos_gem_create(int fd, struct drm_exynos_gem_create *gem)
-{
-       int ret;
-
-       if (!gem) {
-               fprintf(stderr, "gem object is null.\n");
-               return -EFAULT;
-       }
-
-       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CREATE, gem);
-       if (ret < 0) {
-               fprintf(stderr, "failed to create gem buffer: %s\n",
-                               strerror(-ret));
-               return ret;
-       }
-
-       return 0;
-}
-
 static int exynos_gem_map_offset(int fd, struct drm_exynos_gem_map_off *map_off)
 {
        int ret;
@@ -483,13 +649,13 @@ static int exynos_gem_map_offset(int fd, struct drm_exynos_gem_map_off *map_off)
        return 0;
 }
 
-static int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap)
+static int exynos_gem_get_ump(int fd, struct drm_exynos_gem_ump *gem_ump)
 {
        int ret;
 
-       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_MMAP, in_mmap);
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_EXPORT_UMP, gem_ump);
        if (ret < 0) {
-               fprintf(stderr, "failed to get buffer offset: %s\n",
+               fprintf(stderr, "failed to get ump: %s\n",
                                strerror(-ret));
                return ret;
        }
@@ -497,13 +663,14 @@ static int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap)
        return 0;
 }
 
-static int exynos_gem_close(int fd, struct drm_gem_close *gem_close)
+static int exynos_gem_cache_op(int fd,
+                               struct drm_exynos_gem_cache_op *cache_op)
 {
        int ret;
 
-       ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, gem_close);
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CACHE_OP, cache_op);
        if (ret < 0) {
-               fprintf(stderr, "failed to close gem buffer: %s\n",
+               fprintf(stderr, "failed to cache operation: %s\n",
                                strerror(-ret));
                return ret;
        }
@@ -511,13 +678,14 @@ static int exynos_gem_close(int fd, struct drm_gem_close *gem_close)
        return 0;
 }
 
-static int exynos_gem_get_ump(int fd, struct drm_exynos_gem_ump *gem_ump)
+static int exynos_gem_get_phy(int fd,
+                       struct drm_exynos_gem_get_phy *get_phy)
 {
        int ret;
 
-       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_EXPORT_UMP, gem_ump);
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_GET_PHY, get_phy);
        if (ret < 0) {
-               fprintf(stderr, "failed to get ump: %s\n",
+               fprintf(stderr, "failed to get physical address: %s\n",
                                strerror(-ret));
                return ret;
        }
@@ -525,14 +693,14 @@ static int exynos_gem_get_ump(int fd, struct drm_exynos_gem_ump *gem_ump)
        return 0;
 }
 
-static int exynos_gem_cache_op(int fd,
-                               struct drm_exynos_gem_cache_op *cache_op)
+static int exynos_gem_phy_imp(int fd,
+                       struct drm_exynos_gem_phy_imp *phy_imp)
 {
        int ret;
 
-       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CACHE_OP, cache_op);
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_PHY_IMP, phy_imp);
        if (ret < 0) {
-               fprintf(stderr, "failed to cache operation: %s\n",
+               fprintf(stderr, "failed to import physical memory to gem: %s\n",
                                strerror(-ret));
                return ret;
        }
@@ -543,18 +711,12 @@ static int exynos_gem_cache_op(int fd,
 static void
 set_mode(struct connector *c, int count, int page_flip)
 {
-       struct drm_exynos_gem_create gem1, gem2;
-       struct drm_exynos_gem_map_off map_off1, map_off2;
-       struct drm_exynos_gem_mmap mmap1;
-       struct drm_exynos_gem_cache_op cache_op;
-       struct drm_exynos_gem_ump gem_ump;
-       struct drm_gem_close args;
+       struct kms_driver *kms;
+       struct kms_bo *bo, *other_bo;
        unsigned int fb_id, other_fb_id;
        int i, ret, width, height, x, stride;
        unsigned handle;
-       void *usr_addr1, *usr_addr2;
        drmEventContext evctx;
-       unsigned int tmp;
 
        width = 0;
        height = 0;
@@ -567,57 +729,421 @@ set_mode(struct connector *c, int count, int page_flip)
                        height = c[i].mode->vdisplay;
        }
 
-#ifdef CACHE_TEST
-       cache_op.flags = 0;
-       cache_op.flags = (EXYNOS_DRM_ALL_CACHE | EXYNOS_DRM_CACHE_FSH);
+       ret = kms_create(fd, &kms);
+       if (ret) {
+               fprintf(stderr, "failed to create kms driver: %s\n",
+                       strerror(-ret));
+               return;
+       }
 
-       exynos_gem_cache_op(fd, &cache_op);
+       if (create_test_buffer(kms, width, height, &stride, &bo))
+               return;
+
+       kms_bo_get_prop(bo, KMS_HANDLE, &handle);
+       ret = drmModeAddFB(fd, width, height, 24, 32, stride, handle, &fb_id);
+       if (ret) {
+               fprintf(stderr, "failed to add fb (%ux%u): %s\n",
+                       width, height, strerror(errno));
+               return;
+       }
+
+       x = 0;
+       for (i = 0; i < count; i++) {
+               if (c[i].mode == NULL)
+                       continue;
+
+               printf("setting mode %s on connector %d, crtc %d\n",
+                      c[i].mode_str, c[i].id, c[i].crtc);
+
+               ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
+                                    &c[i].id, 1, c[i].mode);
+
+               /* XXX: Actually check if this is needed */
+               drmModeDirtyFB(fd, fb_id, NULL, 0);
+
+               x += c[i].mode->hdisplay;
+
+               if (ret) {
+                       fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
+                       return;
+               }
+       }
+
+       if (!page_flip)
+               return;
+       
+       if (create_grey_buffer(kms, width, height, &stride, &other_bo))
+               return;
+
+       kms_bo_get_prop(other_bo, KMS_HANDLE, &handle);
+       ret = drmModeAddFB(fd, width, height, 32, 32, stride, handle,
+                          &other_fb_id);
+       if (ret) {
+               fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
+               return;
+       }
+
+       for (i = 0; i < count; i++) {
+               if (c[i].mode == NULL)
+                       continue;
+
+               ret = drmModePageFlip(fd, c[i].crtc, other_fb_id,
+                                     DRM_MODE_PAGE_FLIP_EVENT, &c[i]);
+               if (ret) {
+                       fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
+                       return;
+               }
+               gettimeofday(&c[i].start, NULL);
+               c[i].swap_count = 0;
+               c[i].fb_id[0] = fb_id;
+               c[i].fb_id[1] = other_fb_id;
+               c[i].current_fb_id = other_fb_id;
+       }
+
+       memset(&evctx, 0, sizeof evctx);
+       evctx.version = DRM_EVENT_CONTEXT_VERSION;
+       evctx.vblank_handler = NULL;
+       evctx.page_flip_handler = page_flip_handler;
+       
+       while (1) {
+#if 0
+               struct pollfd pfd[2];
+
+               pfd[0].fd = 0;
+               pfd[0].events = POLLIN;
+               pfd[1].fd = fd;
+               pfd[1].events = POLLIN;
+
+               if (poll(pfd, 2, -1) < 0) {
+                       fprintf(stderr, "poll error\n");
+                       break;
+               }
+
+               if (pfd[0].revents)
+                       break;
+#else
+               struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+               fd_set fds;
+               int ret;
+
+               FD_ZERO(&fds);
+               FD_SET(0, &fds);
+               FD_SET(fd, &fds);
+               ret = select(fd + 1, &fds, NULL, NULL, &timeout);
+
+               if (ret <= 0) {
+                       fprintf(stderr, "select timed out or error (ret %d)\n",
+                               ret);
+                       continue;
+               } else if (FD_ISSET(0, &fds)) {
+                       break;
+               }
 #endif
 
-       /* allocate gem buffer. */
-       gem1.size = 1024 * 600 * 4;
+               drmHandleEvent(fd, &evctx);
+       }
 
-       ret = exynos_gem_create(fd, &gem1);
-       if (ret < 0)
+       kms_bo_destroy(&bo);
+       kms_bo_destroy(&other_bo);
+       kms_destroy(&kms);
+}
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "ecpmfs:t:v";
+
+void usage(char *name)
+{
+       fprintf(stderr, "usage: %s [-ecpmfst]\n", name);
+       fprintf(stderr, "\t-e\tlist encoders\n");
+       fprintf(stderr, "\t-c\tlist connectors\n");
+       fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
+       fprintf(stderr, "\t-m\tlist modes\n");
+       fprintf(stderr, "\t-f\tlist framebuffers\n");
+       fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
+       fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\t-t <command_type:allocation_type:cache_attr>\tsetup gem allocation\n");
+       fprintf(stderr, "\t-t <command_type:cache_type:cache_operation>\tsetup cache operation\n");
+       fprintf(stderr, "\t-t <command_type:dmabuf:dmabuf_type>\tsetup drm prime or ump dmabuf\n");
+       fprintf(stderr, "\n\tcommand line sentences to -t option\n");
+       fprintf(stderr, "\t-t alloc:[contig,noncontig,userptr]:[cache,noncache,writecombine]\n");
+       fprintf(stderr, "\t-t cache:[l1,l2,all]:[flush_range,clean_range,inv_range,flush_all,clean_all,inv_all]\n");
+       fprintf(stderr, "\t-t [prime,ump]:dmabuf:[export,import,all]\n");
+       fprintf(stderr, "\n\tDefault is to dump all info.\n");
+       exit(0);
+}
+
+#define dump_resource(res) if (res) dump_##res()
+
+static int page_flipping_supported(int fd)
+{
+       /*FIXME: generic ioctl needed? */
+       return 1;
+#if 0
+       int ret, value;
+       struct drm_i915_getparam gp;
+
+       gp.param = I915_PARAM_HAS_PAGEFLIPPING;
+       gp.value = &value;
+
+       ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
+       if (ret) {
+               fprintf(stderr, "drm_i915_getparam: %m\n");
+               return 0;
+       }
+
+       return *gp.value;
+#endif
+}
+
+static void test_exynos_gem(struct connector *c, int count, int page_flip)
+{
+       struct drm_exynos_gem_map_off map_off1;
+
+       struct drm_exynos_gem_cache_op cache_op;
+
+       struct ump_uk_dmabuf ump_dmabuf;
+       int ump_fd;
+
+       void *vaddr;
+
+       struct kms_driver *kms;
+       struct kms_bo *other_bo;
+       int i, ret, width, height, x, stride;
+       unsigned int fb_id, other_fb_id;
+       uint32_t handle;
+       drmEventContext evctx;
+       void *usr_addr1;
+       int prime_fd;
+
+       struct exynos_device *dev;
+       struct exynos_bo *bo;
+       unsigned int gem_size, gem_flags;
+
+#if 0
+#ifdef UMP_TEST
+       struct drm_exynos_gem_ump gem_ump;
+#endif
+#ifdef GET_PHY_TEST
+       /* temporary codes. */
+       struct drm_exynos_gem_get_phy get_phy;
+       struct drm_exynos_gem_phy_imp phy_imp;
+#endif
+#ifdef VIDI_TEST
+       struct drm_exynos_vidi_connection vidi;
+#endif
+#ifdef GEMGET_TEST
+       struct drm_exynos_gem_info info;
+#endif
+#ifdef VIDI_TEST
+       vidi.connection = 1;
+       exynos_vidi_connection(fd, &vidi);
+#endif
+#endif
+
+       dev = exynos_device_create(fd);
+       if (!dev)
                return;
 
-       handle = gem1.handle;
+       exynos_test_dump();
+
+       width = 0;
+       height = 0;
+       for (i = 0; i < count; i++) {
+               connector_find_mode(&c[i]);
+               if (c[i].mode == NULL)
+                       continue;
+               width += c[i].mode->hdisplay;
+               if (height < c[i].mode->vdisplay)
+                       height = c[i].mode->vdisplay;
+       }
+
+       if (exynos_test.cmd_type & CMD_ALLOC) {
+               if (exynos_test.mem_type & ALLOC_USERPTR) {
+                       vaddr = malloc(DEFAULT_SIZE);
+                       if (!vaddr)
+                               return;
+
+                       ret = exynos_userptr(dev, vaddr, DEFAULT_SIZE, &handle);
+                       if (ret < 0)
+                               return;
+
+                       usr_addr1 = vaddr;
+                       printf("userptr handle = %d\n", handle);
+               } else {
+                       unsigned int flags;
+
+                       /* flag memory type. */
+                       if (exynos_test.mem_type & ALLOC_CONTIG)
+                               flags = EXYNOS_BO_CONTIG;
+                       else
+                               flags = EXYNOS_BO_NONCONTIG;
+
+                       /* flag cache mapping type. */
+                       if (exynos_test.map_type & ALLOC_MAP_C)
+                               flags |= EXYNOS_BO_CACHABLE;
+                       else if (exynos_test.map_type & ALLOC_MAP_NC)
+                               flags |= EXYNOS_BO_NONCACHABLE;
+                       else
+                               flags |= EXYNOS_BO_WC;
+
+                       bo = exynos_bo_create(dev, DEFAULT_SIZE, flags);
+                       if (!bo)
+                               return;
+
+                       handle = bo->handle;
+
+                       printf("gem handle = %d\n", bo->handle);
+               }
+       }
 
 #ifdef DIRECT_MAP
-       mmap1.handle = handle;
-       mmap1.size = gem1.size;
-       ret = exynos_gem_mmap(fd, &mmap1);
-       if (ret < 0)
-               return;
+       if (!(exynos_test.mem_type & ALLOC_USERPTR)) {
+               printf("handle = %d, size = 0x%x\n", bo->handle, bo->size);
+
+               usr_addr1 = exynos_bo_map(bo);
+               if (!usr_addr1)
+                       return;
 
-       usr_addr1 = mmap1.mapped;
-       memset(usr_addr1, 0x88, mmap1.size);
+               memset(usr_addr1, 0x88, bo->size);
+       }
 #endif
 #ifdef INDIRECT_MAP
-       map_off1.handle = handle;
+       /* FIXME */
+       if (!(exynos_test.mem_type & ALLOC_USERPTR)) {
+               map_off1.handle = handle;
+
+               /* get map offset. */
+               ret = exynos_gem_map_offset(fd, &map_off1);
+               if (ret < 0)
+                       return;
 
-       /* get map offset. */
-       ret = exynos_gem_map_offset(fd, &map_off1);
+               usr_addr1 = mmap(0, gem1.size, PROT_READ | PROT_WRITE,
+                               MAP_SHARED, fd, map_off1.offset);
+
+               memset(usr_addr1, 0x88, gem1.size);
+       }
+#endif
+
+       if (exynos_test.cmd_type & CMD_CACHE) {
+               cache_op.flags = 0;
+
+               /* flag cache units to do cache operation. */
+               if (exynos_test.cache_type & CACHE_L1)
+                       cache_op.flags |= EXYNOS_DRM_L1_CACHE;
+               if (exynos_test.cache_type & CACHE_L2)
+                       cache_op.flags |= EXYNOS_DRM_L2_CACHE;
+               if (exynos_test.cache_type & CACHE_ALL_CORES)
+                       cache_op.flags |= EXYNOS_DRM_ALL_CORES;
+
+               /* flag cache operations. */
+               if (exynos_test.cache_op_type & CACHE_CLEAN_RANGE)
+                       cache_op.flags |= EXYNOS_DRM_CACHE_CLN_RANGE;
+               if (exynos_test.cache_op_type & CACHE_INV_RANGE)
+                       cache_op.flags |= EXYNOS_DRM_CACHE_INV_RANGE;
+               if (!(exynos_test.cache_op_type & CACHE_CLEAN_RANGE)) {
+                       cache_op.flags &= ~EXYNOS_DRM_CACHE_CLN_RANGE;
+                       cache_op.flags |= EXYNOS_DRM_CACHE_CLN_ALL;
+               }
+               if (!(exynos_test.cache_op_type & CACHE_INV_RANGE)) {
+                       cache_op.flags &= ~EXYNOS_DRM_CACHE_INV_RANGE;
+                       cache_op.flags |= EXYNOS_DRM_CACHE_INV_ALL;
+               }
+
+               cache_op.usr_addr = usr_addr1 + exynos_test.start_offset;
+               cache_op.size = exynos_test.end_offset -
+                               exynos_test.start_offset;
+
+               exynos_gem_cache_op(fd, &cache_op);
+       }
+
+#ifdef GEMGET_TEST
+       ret = exynos_bo_gem_info(dev, bo->handle, &gem_size, &gem_flags);
        if (ret < 0)
                return;
 
-       usr_addr1 = mmap(0, gem1.size, PROT_READ | PROT_WRITE,
-                       MAP_SHARED, fd, map_off1.offset);
+       printf("[gem get] flags = 0x%x, size = 0x%x\n", gem_flags, gem_size);
+#endif
+
+       if (exynos_test.cmd_type & CMD_PRIME) {
+               if (exynos_test.dmabuf_type & DMABUF_EXPORT) {
+                       ret = exynos_prime_handle_to_fd(dev, bo->handle,
+                                                               &prime_fd);
+                       if (ret < 0)
+                               return;
+
+                       printf("handle to fd : handle(0x%x) ==> fd(%d)\n",
+                                                               bo->handle,
+                                                               prime_fd);
+               }
+
+               if (exynos_test.dmabuf_type & DMABUF_IMPORT) {
+                       uint32_t gem_handle;
+
+                       ret = exynos_prime_fd_to_handle(dev, prime_fd, &gem_handle);
+                       if (ret < 0)
+                               return;
+
+                       printf("fd to handle : fd(%d) ==> handle(0x%x)\n",
+                                                               prime_fd,
+                                                               gem_handle);
+               }
+       }
+
+       if (exynos_test.cmd_type & CMD_UMP) {
+               ump_fd = open("/dev/ump", O_RDWR);
+               if (ump_fd < 0) {
+                       printf("failed to open ump.\n");
+                       return;
+               }
+
+               memset(&ump_dmabuf, 0, sizeof(struct ump_uk_dmabuf));
+
+               if (exynos_test.dmabuf_type & DMABUF_IMPORT) {
+                       ump_dmabuf.fd = prime_fd;
+                       ret = ioctl(ump_fd, UMP_IOC_DMABUF_IMPORT, &ump_dmabuf);
+                       if (ret < 0) {
+                               printf("failed to ioctl ump.\n");
+                               return;
+                       }
+
+                       printf("ump handle = 0x%x\n", ump_dmabuf.ump_handle);
+               }
+
+               close(ump_fd);
+       }
 
-       memset(usr_addr1, 0x88, gem1.size);
+#if 0
+#ifdef GET_PHY_TEST
+       memset(&get_phy, 0, sizeof(struct drm_exynos_gem_get_phy));
+       get_phy.gem_handle = handle;
+       exynos_gem_get_phy(fd, &get_phy);
+       printf("get_phy->phy_addr = 0x%llx, get_phy->size = 0x%llx\n",
+                       get_phy.phy_addr, get_phy.size);
+
+       memset(&phy_imp, 0, sizeof(struct drm_exynos_gem_phy_imp));
+       phy_imp.phy_addr = get_phy.phy_addr;
+       phy_imp.size = get_phy.size;
+       exynos_gem_phy_imp(fd, &phy_imp);
+       printf("phy_imp->handle = 0x%x\n", phy_imp.gem_handle);
 #endif
 
+#ifdef UMP_TEST
        /* get secure id for ump. */
        gem_ump.gem_handle = handle;
 
        exynos_gem_get_ump(fd, &gem_ump);
 
        printf("secure id = %d\n", gem_ump.secure_id);
+#endif
+#endif
+       stride = width * 4;
 
        ret = drmModeAddFB(fd, width, height, 32, 32, stride, handle, &fb_id);
        if (ret) {
                fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
-               return;
+               goto err;
        }
 
        x = 0;
@@ -630,6 +1156,10 @@ set_mode(struct connector *c, int count, int page_flip)
 
                ret = drmModeSetCrtc(fd, c[i].crtc, fb_id, x, 0,
                                     &c[i].id, 1, c[i].mode);
+
+               /* XXX: Actually check if this is needed */
+               drmModeDirtyFB(fd, fb_id, NULL, 0);
+
                x += c[i].mode->hdisplay;
 
                if (ret) {
@@ -641,26 +1171,17 @@ set_mode(struct connector *c, int count, int page_flip)
        if (!page_flip)
                return;
 
-       /* for second gem object, INDIRECT_MODE would be used. */
-
-       gem2.size = 1024 * 600 * 4;
-
-       /* allocate gem buffer. */
-       ret = exynos_gem_create(fd, &gem2);
-       if (ret < 0)
+       ret = kms_create(fd, &kms);
+       if (ret) {
+               fprintf(stderr, "failed to create kms driver: %s\n",
+                       strerror(-ret));
                return;
+       }
 
-       handle = map_off2.handle = gem2.handle;
-
-       /* get map offset. */
-       ret = exynos_gem_map_offset(fd, &map_off2);
-       if (ret < 0)
+       if (create_test_buffer(kms, width, height, &stride, &other_bo))
                return;
 
-       usr_addr2 = mmap(0, gem2.size, PROT_READ | PROT_WRITE,
-                       MAP_SHARED, fd, map_off2.offset);
-
-       memset(usr_addr2, 0x0, gem2.size);
+       kms_bo_get_prop(other_bo, KMS_HANDLE, &handle);
        ret = drmModeAddFB(fd, width, height, 32, 32, stride, handle,
                           &other_fb_id);
        if (ret) {
@@ -672,8 +1193,12 @@ set_mode(struct connector *c, int count, int page_flip)
                if (c[i].mode == NULL)
                        continue;
 
-               drmModePageFlip(fd, c[i].crtc, other_fb_id,
-                               DRM_MODE_PAGE_FLIP_EVENT, &c[i]);
+               ret = drmModePageFlip(fd, c[i].crtc, other_fb_id,
+                                     DRM_MODE_PAGE_FLIP_EVENT, &c[i]);
+               if (ret) {
+                       fprintf(stderr, "failed to page flip: %s\n", strerror(errno));
+                       return;
+               }
                gettimeofday(&c[i].start, NULL);
                c[i].swap_count = 0;
                c[i].fb_id[0] = fb_id;
@@ -707,65 +1232,128 @@ set_mode(struct connector *c, int count, int page_flip)
                drmHandleEvent(fd, &evctx);
        }
 
-       /* release user space memroy. */
-#if defined(INDIRECT_MAP) || defined(DIRECT_MAP)
-       munmap(usr_addr1, mmap1.size);
-#endif
-       munmap(usr_addr2, gem2.size);
+       kms_bo_destroy(&other_bo);
+       kms_destroy(&kms);
 
-       args.handle = gem1.handle;
+err:
+       if (exynos_test.mem_type == ALLOC_USERPTR) {
+               struct drm_gem_close gem_close;
 
-       /* relese gem buffer. */
-       ret = exynos_gem_close(fd, &args);
-       if (ret < 0)
-               return;
+               gem_close.handle = handle;
 
-       args.handle = gem2.handle;
-       ret = exynos_gem_close(fd, &args);
-       if (ret < 0)
-               return;
+               free(usr_addr1);
+               drmIoctl(fd, DRM_IOCTL_GEM_CLOSE, &gem_close);
+       } else
+               exynos_bo_destroy(bo);
 }
 
-extern char *optarg;
-extern int optind, opterr, optopt;
-static char optstr[] = "ecpmfs:v";
 
-void usage(char *name)
+static int setup_exynos_gem_map_type(void)
 {
-       fprintf(stderr, "usage: %s [-ecpmf]\n", name);
-       fprintf(stderr, "\t-e\tlist encoders\n");
-       fprintf(stderr, "\t-c\tlist connectors\n");
-       fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
-       fprintf(stderr, "\t-m\tlist modes\n");
-       fprintf(stderr, "\t-f\tlist framebuffers\n");
-       fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
-       fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
-       fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
-       fprintf(stderr, "\n\tDefault is to dump all info.\n");
-       exit(0);
+       if (strncmp(exynos_test.scmd[2], "cache", 5) == 0)
+               exynos_test.map_type = ALLOC_MAP_C;
+       else if (strncmp(exynos_test.scmd[2], "noncache", 8) == 0)
+               exynos_test.map_type = ALLOC_MAP_NC;
+       else if (strncmp(exynos_test.scmd[2], "writecombine", 12) == 0)
+               exynos_test.map_type = ALLOC_MAP_WC;
+       else {
+               printf("invalid map type.\n");
+               return -EINVAL;
+       }
+
+       return 0;
 }
 
-#define dump_resource(res) if (res) dump_##res()
+static int setup_exynos_gem_cache_op_type(void)
+{
+       if (strncmp(exynos_test.scmd[2], "clean_range", 11) == 0)
+               exynos_test.cache_op_type |= CACHE_CLEAN_RANGE;
+       else if (strncmp(exynos_test.scmd[2], "inv_range", 9) == 0)
+               exynos_test.cache_op_type |= CACHE_INV_RANGE;
+       else if (strncmp(exynos_test.scmd[2], "flush_range", 11) == 0)
+               exynos_test.cache_op_type |= CACHE_FLUSH_RANGE;
+       else if (strncmp(exynos_test.scmd[2], "clean_all", 9) == 0)
+               exynos_test.cache_op_type &= ~CACHE_CLEAN_RANGE; /* all */
+       else if (strncmp(exynos_test.scmd[2], "inv_all", 7) == 0)
+               exynos_test.cache_op_type &= ~CACHE_INV_RANGE; /* all */
+       else if (strncmp(exynos_test.scmd[2], "flush_all", 9) == 0)
+               exynos_test.cache_op_type &= ~CACHE_FLUSH_RANGE; /* all */
+       else {
+               printf("invalid cache op type.\n");
+               return -EINVAL;
+       }
 
-static int page_flipping_supported(int fd)
+       return 0;
+}
+
+static int setup_exynos_gem_dmabuf_type(void)
 {
-       /*FIXME: generic ioctl needed? */
-       return 1;
-#if 0
-       int ret, value;
-       struct drm_i915_getparam gp;
+       if (strncmp(exynos_test.scmd[2], "export", 6) == 0)
+               exynos_test.dmabuf_type |= DMABUF_EXPORT;
+       else if (strncmp(exynos_test.scmd[2], "import", 6) == 0)
+               exynos_test.dmabuf_type |= DMABUF_IMPORT;
+       else if (strncmp(exynos_test.scmd[2], "all", 3) == 0)
+               exynos_test.dmabuf_type |= DMABUF_ALL;
+       else {
+               printf("invalid dmabuf type.\n");
+               return -EINVAL;
+       }
 
-       gp.param = I915_PARAM_HAS_PAGEFLIPPING;
-       gp.value = &value;
+       return 0;
+}
 
-       ret = drmCommandWriteRead(fd, DRM_I915_GETPARAM, &gp, sizeof(gp));
-       if (ret) {
-               fprintf(stderr, "drm_i915_getparam: %m\n");
-               return 0;
+static int setup_exynos_gem_test(void)
+{
+       if (strncmp(exynos_test.scmd[0], "alloc", 5) == 0) {
+               exynos_test.cmd_type |= CMD_ALLOC;
+
+               if (strncmp(exynos_test.scmd[1], "contig", 5) == 0)
+                       exynos_test.mem_type = ALLOC_CONTIG;
+               else if (strncmp(exynos_test.scmd[1], "noncontig", 8) == 0)
+                       exynos_test.mem_type = ALLOC_NONCONTIG;
+               else if (strncmp(exynos_test.scmd[1], "userptr", 7) == 0)
+                       exynos_test.mem_type = ALLOC_USERPTR;
+               else {
+                       printf("invalid option type.\n");
+                       return -EINVAL;
+               }
+
+               return setup_exynos_gem_map_type();
+       } else if (strncmp(exynos_test.scmd[0], "cache", 5) == 0) {
+               exynos_test.cmd_type |= CMD_CACHE;
+
+               if (strncmp(exynos_test.scmd[1], "l1", 2) == 0) {
+                       exynos_test.cache_type |= CACHE_L1;
+               } else if (strncmp(exynos_test.scmd[1], "l2", 2) == 0) {
+                       exynos_test.cache_type |= CACHE_L2;
+               } else if (strncmp(exynos_test.scmd[1], "all", 3) == 0) {
+                       exynos_test.cache_type |= CACHE_ALL_CACHES;
+               } else if (strncmp(exynos_test.scmd[1], "all_cores", 9) == 0) {
+                       exynos_test.cache_type |= CACHE_ALL_CACHES_CORES;
+               } else {
+                       printf("invalid option type.\n");
+                       return -EINVAL;
+               }
+
+               return setup_exynos_gem_cache_op_type();
+       } else if ((strncmp(exynos_test.scmd[0], "prime", 5) == 0) ||
+                       (strncmp(exynos_test.scmd[0], "ump", 3) == 0)) {
+               exynos_test.cmd_type |= (strncmp(exynos_test.scmd[0],
+                                               "prime", 5) == 0) ?
+                                               CMD_PRIME : CMD_UMP;
+
+               if (strncmp(exynos_test.scmd[1], "dmabuf", 6) == 0)
+                       return setup_exynos_gem_dmabuf_type();
+               else {
+                       printf("invalid option type.\n");
+                       return -EINVAL;
+               }
+       } else {
+               printf("invalid command type.\n");
+               return -EINVAL;
        }
 
-       return *gp.value;
-#endif
+       return 0;
 }
 
 int main(int argc, char **argv)
@@ -773,12 +1361,13 @@ int main(int argc, char **argv)
        int c;
        int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
        int test_vsync = 0;
-       char *modules[] = { "exynos-drm", "i915", "radeon", "nouveau" };
+       char *modules[] = { "exynos", "i915", "radeon", "nouveau" };
        char *modeset = NULL;
-       int i, count = 0;
+       int i, count = 0, private_test = 0, cmd_cnt = 0, ret = 0;
        struct connector con_args[2];
-       
+
        opterr = 0;
+
        while ((c = getopt(argc, argv, optstr)) != -1) {
                switch (c) {
                case 'e':
@@ -810,7 +1399,23 @@ int main(int argc, char **argv)
                                   &con_args[count].crtc,
                                   con_args[count].mode_str) != 3)
                                usage(argv[0]);
-                       count++;                                      
+                       count++;
+                       break;
+               case 't':
+                       modeset = strdup(optarg);
+                       exynos_test.scmd[cmd_cnt++] = strtok(modeset, ":~");
+                       while (exynos_test.scmd[cmd_cnt++] = strtok(NULL, ":~"));
+
+                       cmd_cnt--;
+                       if (cmd_cnt != 3 && cmd_cnt != 5)
+                               usage(argv[0]);
+
+                       ret = setup_exynos_gem_test();
+                       if (ret < 0)
+                               return ret;
+
+                       private_test = 1;
+                       cmd_cnt = 0;
                        break;
                default:
                        usage(argv[0]);
@@ -856,7 +1461,11 @@ int main(int argc, char **argv)
        dump_resource(framebuffers);
 
        if (count > 0) {
-               set_mode(con_args, count, test_vsync);
+               if (private_test)
+                       test_exynos_gem(con_args, count, test_vsync);
+               else
+                       set_mode(con_args, count, test_vsync);
+
                getchar();
        }
 
diff --git a/tests/gemtest/ump.h b/tests/gemtest/ump.h
new file mode 100644 (file)
index 0000000..8e45825
--- /dev/null
@@ -0,0 +1,262 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump.h
+ *
+ * This file contains the user space part of the UMP API.
+ */
+
+#ifndef _UNIFIED_MEMORY_PROVIDER_H_
+#define _UNIFIED_MEMORY_PROVIDER_H_
+
+
+/** @defgroup ump_user_space_api UMP User Space API
+ * @{ */
+
+
+#include "ump_platform.h"
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * External representation of a UMP handle in user space.
+ */
+typedef void * ump_handle;
+
+/**
+ * Typedef for a secure ID, a system wide identificator for UMP memory buffers.
+ */
+typedef unsigned int ump_secure_id;
+
+/**
+ * Value to indicate an invalid UMP memory handle.
+ */
+#define UMP_INVALID_MEMORY_HANDLE ((ump_handle)0)
+
+/**
+ * Value to indicate an invalid secure Id.
+ */
+#define UMP_INVALID_SECURE_ID     ((ump_secure_id)-1)
+
+/**
+ * UMP error codes for user space.
+ */
+typedef enum
+{
+       UMP_OK,    /**< indicates success */
+       UMP_ERROR, /**< indicates failure */
+} ump_result;
+
+
+/**
+ * Opens and initializes the UMP library.
+ *
+ * This function must be called at least once before calling any other UMP API functions.
+ * Each open is reference counted and must be matched with a call to @ref ump_close "ump_close".
+ *
+ * @see ump_close
+ *
+ * @return UMP_OK indicates success, UMP_ERROR indicates failure.
+ */
+UMP_API_EXPORT ump_result ump_open(void);
+
+
+/**
+ * Terminate the UMP library.
+ *
+ * This must be called once for every successful @ref ump_open "ump_open". The UMP library is
+ * terminated when, and only when, the last open reference to the UMP interface is closed.
+ *
+ * @see ump_open
+ */
+UMP_API_EXPORT void ump_close(void);
+
+
+/**
+ * Retrieves the secure ID for the specified UMP memory.
+ *
+ * This identificator is unique across the entire system, and uniquely identifies
+ * the specified UMP memory. This identificator can later be used through the
+ * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id" or
+ * @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id"
+ * functions in order to access this UMP memory, for instance from another process.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_secure_id_get "ump_dd_secure_id_get"
+ *
+ * @see ump_handle_create_from_secure_id
+ * @see ump_dd_handle_create_from_secure_id
+ * @see ump_dd_secure_id_get
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return Returns the secure ID for the specified UMP memory.
+ */
+UMP_API_EXPORT ump_secure_id ump_secure_id_get(ump_handle mem);
+
+
+/**
+ * Retrieves a handle to allocated UMP memory.
+ *
+ * The usage of UMP memory is reference counted, so this will increment the reference
+ * count by one for the specified UMP memory.
+ * Use @ref ump_reference_release "ump_reference_release" when there is no longer any
+ * use for the retrieved handle.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_handle_create_from_secure_id "ump_dd_handle_create_from_secure_id"
+ *
+ * @see ump_reference_release
+ * @see ump_dd_handle_create_from_secure_id
+ *
+ * @param secure_id The secure ID of the UMP memory to open, that can be retrieved using the @ref ump_secure_id_get "ump_secure_id_get " function.
+ *
+ * @return UMP_INVALID_MEMORY_HANDLE indicates failure, otherwise a valid handle is returned.
+ */
+UMP_API_EXPORT ump_handle ump_handle_create_from_secure_id(ump_secure_id secure_id);
+
+
+/**
+ * Retrieves the actual size of the specified UMP memory.
+ *
+ * The size is reported in bytes, and is typically page aligned.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_size_get "ump_dd_size_get"
+ *
+ * @see ump_dd_size_get
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return Returns the allocated size of the specified UMP memory, in bytes.
+ */
+UMP_API_EXPORT unsigned long ump_size_get(ump_handle mem);
+
+
+/**
+ * Read from specified UMP memory.
+ *
+ * Another way of reading from (and writing to) UMP memory is to use the
+ * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve
+ * a CPU mapped pointer to the memory.
+ *
+ * @see ump_mapped_pointer_get
+ *
+ * @param dst Destination buffer.
+ * @param src Handle to UMP memory to read from.
+ * @param offset Where to start reading, given in bytes.
+ * @param length How much to read, given in bytes.
+ */
+UMP_API_EXPORT void ump_read(void * dst, ump_handle src, unsigned long offset, unsigned long length);
+
+
+/**
+ * Write to specified UMP memory.
+ *
+ * Another way of writing to (and reading from) UMP memory is to use the
+ * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" to retrieve
+ * a CPU mapped pointer to the memory.
+ *
+ * @see ump_mapped_pointer_get
+ *
+ * @param dst Handle to UMP memory to write to.
+ * @param offset Where to start writing, given in bytes.
+ * @param src Buffer to read from.
+ * @param length How much to write, given in bytes.
+ */
+UMP_API_EXPORT void ump_write(ump_handle dst, unsigned long offset, const void * src, unsigned long length);
+
+
+/**
+ * Retrieves a memory mapped pointer to the specified UMP memory.
+ *
+ * This function retrieves a memory mapped pointer to the specified UMP memory,
+ * that can be used by the CPU. Every successful call to
+ * @ref ump_mapped_pointer_get "ump_mapped_pointer_get" is reference counted,
+ * and must therefor be followed by a call to
+ * @ref ump_mapped_pointer_release "ump_mapped_pointer_release " when the
+ * memory mapping is no longer needed.
+ *
+ * @note Systems without a MMU for the CPU only return the physical address, because no mapping is required.
+ *
+ * @see ump_mapped_pointer_release
+ *
+ * @param mem Handle to UMP memory.
+ *
+ * @return NULL indicates failure, otherwise a CPU mapped pointer is returned.
+ */
+UMP_API_EXPORT void * ump_mapped_pointer_get(ump_handle mem);
+
+
+/**
+ * Releases a previously mapped pointer to the specified UMP memory.
+ *
+ * The CPU mapping of the specified UMP memory memory is reference counted,
+ * so every call to @ref ump_mapped_pointer_get "ump_mapped_pointer_get" must
+ * be matched with a call to this function when the mapping is no longer needed.
+ *
+ * The CPU mapping is not removed before all references to the mapping is released.
+ *
+ * @note Systems without a MMU must still implement this function, even though no unmapping should be needed.
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_API_EXPORT void ump_mapped_pointer_release(ump_handle mem);
+
+
+/**
+ * Adds an extra reference to the specified UMP memory.
+ *
+ * This function adds an extra reference to the specified UMP memory. This function should
+ * be used every time a UMP memory handle is duplicated, that is, assigned to another ump_handle
+ * variable. The function @ref ump_reference_release "ump_reference_release" must then be used
+ * to release each copy of the UMP memory handle.
+ *
+ * @note You are not required to call @ref ump_reference_add "ump_reference_add"
+ * for UMP handles returned from
+ * @ref ump_handle_create_from_secure_id "ump_handle_create_from_secure_id",
+ * because these handles are already reference counted by this function.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_reference_add "ump_dd_reference_add"
+ *
+ * @see ump_dd_reference_add
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_API_EXPORT void ump_reference_add(ump_handle mem);
+
+
+/**
+ * Releases a reference from the specified UMP memory.
+ *
+ * This function should be called once for every reference to the UMP memory handle.
+ * When the last reference is released, all resources associated with this UMP memory
+ * handle are freed.
+ *
+ * @note There is a kernel space equivalent function called @ref ump_dd_reference_release "ump_dd_reference_release"
+ *
+ * @see ump_dd_reference_release
+ *
+ * @param mem Handle to UMP memory.
+ */
+UMP_API_EXPORT void ump_reference_release(ump_handle mem);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+
+/** @} */ /* end group ump_user_space_api */
+
+
+#endif /*_UNIFIED_MEMORY_PROVIDER_H_ */
diff --git a/tests/gemtest/ump_platform.h b/tests/gemtest/ump_platform.h
new file mode 100644 (file)
index 0000000..9285aef
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2008-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_platform.h
+ *
+ * This file should define UMP_API_EXPORT,
+ * which dictates how the UMP user space API should be exported/imported.
+ * Modify this file, if needed, to match your platform setup.
+ */
+
+#ifndef __UMP_PLATFORM_H__
+#define __UMP_PLATFORM_H__
+
+/** @addtogroup ump_user_space_api
+ * @{ */
+
+/**
+ * A define which controls how UMP user space API functions are imported and exported.
+ * This define should be set by the implementor of the UMP API.
+ */
+#if defined(_WIN32)
+
+#define UMP_API_EXPORT
+
+#elif defined(__SYMBIAN32__)
+
+#define UMP_API_EXPORT IMPORT_C
+
+#else
+
+#define UMP_API_EXPORT
+
+#endif
+
+/** @} */ /* end group ump_user_space_api */
+
+
+#endif /* __UMP_PLATFORM_H__ */
diff --git a/tests/gemtest/ump_ref_drv.h b/tests/gemtest/ump_ref_drv.h
new file mode 100644 (file)
index 0000000..32716ec
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * This confidential and proprietary software may be used only as
+ * authorised by a licensing agreement from ARM Limited
+ * (C) COPYRIGHT 2009-2010 ARM Limited
+ * ALL RIGHTS RESERVED
+ * The entire notice above must be reproduced on all authorised
+ * copies and copies may only be made to the extent permitted
+ * by a licensing agreement from ARM Limited.
+ */
+
+/**
+ * @file ump_ref_drv.h
+ *
+ * Reference driver extensions to the UMP user space API for allocating UMP memory
+ */
+
+#ifndef _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_
+#define _UNIFIED_MEMORY_PROVIDER_REF_DRV_H_
+
+#include "ump.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define UMP_IOCTL_NR   0x90
+
+typedef enum
+{
+       /* This enum must match with the IOCTL enum in ump_ioctl.h */
+       UMP_REF_DRV_CONSTRAINT_NONE = 0,
+       UMP_REF_DRV_CONSTRAINT_PHYSICALLY_LINEAR = 1,
+       UMP_REF_DRV_CONSTRAINT_USE_CACHE = 128,
+} ump_alloc_constraints;
+
+typedef enum
+{
+       UMP_MSYNC_CLEAN = 0 ,
+       UMP_MSYNC_CLEAN_AND_INVALIDATE = 1,
+       UMP_MSYNC_READOUT_CACHE_ENABLED = 128,
+} ump_cpu_msync_op;
+
+struct ump_uk_dmabuf {
+       void            *ctx;
+       int             fd;
+       size_t          size;
+       uint32_t        ump_handle;
+};
+
+#define _UMP_IOC_DMABUF_IMPORT 8
+
+#define UMP_IOC_DMABUF_IMPORT  _IOW(UMP_IOCTL_NR, _UMP_IOC_DMABUF_IMPORT,\
+                                       struct ump_uk_dmabuf)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*_UNIFIED_MEMORY_PROVIDER_REF_DRV_H_ */
diff --git a/tests/ipptest/Makefile.am b/tests/ipptest/Makefile.am
new file mode 100644 (file)
index 0000000..cae05c9
--- /dev/null
@@ -0,0 +1,21 @@
+AM_CFLAGS = \
+       -I$(top_srcdir)/include/drm \
+       -I$(top_srcdir)/libkms/ \
+       -I$(top_srcdir)/exynos/ \
+       -I$(top_srcdir) \
+       $(CAIRO_CFLAGS)
+
+noinst_PROGRAMS = \
+       ipptest
+
+ipptest_SOURCES = \
+       fimctest.c \
+       gem.c \
+       util.c \
+       fimc.c
+
+ipptest_LDADD = \
+       $(top_builddir)/libdrm.la \
+       $(top_builddir)/libkms/libkms.la \
+       $(top_builddir)/exynos/libdrm_exynos.la \
+       $(CAIRO_LIBS)
diff --git a/tests/ipptest/fimc.c b/tests/ipptest/fimc.c
new file mode 100644 (file)
index 0000000..089b707
--- /dev/null
@@ -0,0 +1,538 @@
+/*
+ * DRM based fimc test program
+ * Copyright 2012 Samsung Electronics
+ *   Eunchul Kim <chulspro.kim@sasmsung.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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include "exynos_drm.h"
+#include "fimctest.h"
+#include "gem.h"
+#include "util.h"
+
+#include "drm_fourcc.h"
+
+static int exynos_drm_ipp_property(int fd,
+                               struct drm_exynos_ipp_property *property,
+                               struct drm_exynos_sz *def_sz,
+                               enum drm_exynos_ipp_cmd cmd,
+                               enum drm_exynos_degree degree)
+{
+       struct drm_exynos_pos crop_pos = {0, 0, def_sz->hsize, def_sz->vsize};
+       struct drm_exynos_pos scale_pos = {0, 0, def_sz->hsize, def_sz->vsize};
+       struct drm_exynos_sz src_sz = {def_sz->hsize, def_sz->vsize};
+       struct drm_exynos_sz dst_sz = {def_sz->hsize, def_sz->vsize};
+       int ret = 0;
+
+       memset(property, 0x00, sizeof(struct drm_exynos_ipp_property));
+
+       switch(cmd) {
+       case IPP_CMD_M2M:
+               property->config[EXYNOS_DRM_OPS_SRC].ops_id = EXYNOS_DRM_OPS_SRC;
+               property->config[EXYNOS_DRM_OPS_SRC].flip = EXYNOS_DRM_FLIP_NONE;
+               property->config[EXYNOS_DRM_OPS_SRC].degree = EXYNOS_DRM_DEGREE_0;
+               property->config[EXYNOS_DRM_OPS_SRC].fmt = DRM_FORMAT_XRGB8888;
+               property->config[EXYNOS_DRM_OPS_SRC].pos = crop_pos;
+               property->config[EXYNOS_DRM_OPS_SRC].sz = src_sz;
+
+               property->config[EXYNOS_DRM_OPS_DST].ops_id = EXYNOS_DRM_OPS_DST;
+               property->config[EXYNOS_DRM_OPS_DST].flip = EXYNOS_DRM_FLIP_NONE;
+               property->config[EXYNOS_DRM_OPS_DST].degree = degree;
+               property->config[EXYNOS_DRM_OPS_DST].fmt = DRM_FORMAT_XRGB8888;
+               if (property->config[EXYNOS_DRM_OPS_DST].degree == EXYNOS_DRM_DEGREE_90) {
+                       dst_sz.hsize = def_sz->vsize;
+                       dst_sz.vsize = def_sz->hsize;
+
+                       scale_pos.w = def_sz->vsize;
+                       scale_pos.h = def_sz->hsize;
+               }
+               property->config[EXYNOS_DRM_OPS_DST].pos = scale_pos;
+               property->config[EXYNOS_DRM_OPS_DST].sz = dst_sz;
+               break;
+       case IPP_CMD_WB:
+               property->config[EXYNOS_DRM_OPS_SRC].ops_id = EXYNOS_DRM_OPS_SRC;
+               property->config[EXYNOS_DRM_OPS_SRC].flip = EXYNOS_DRM_FLIP_NONE;
+               property->config[EXYNOS_DRM_OPS_SRC].degree = EXYNOS_DRM_DEGREE_0;
+               property->config[EXYNOS_DRM_OPS_SRC].fmt = DRM_FORMAT_YUV444;
+               property->config[EXYNOS_DRM_OPS_SRC].pos = crop_pos;
+               property->config[EXYNOS_DRM_OPS_SRC].sz = src_sz;
+
+               property->config[EXYNOS_DRM_OPS_DST].ops_id = EXYNOS_DRM_OPS_DST;
+               property->config[EXYNOS_DRM_OPS_DST].flip = EXYNOS_DRM_FLIP_NONE;
+               property->config[EXYNOS_DRM_OPS_DST].degree = degree;
+               property->config[EXYNOS_DRM_OPS_DST].fmt = DRM_FORMAT_XRGB8888;
+               if (property->config[EXYNOS_DRM_OPS_DST].degree == EXYNOS_DRM_DEGREE_90) {
+                       dst_sz.hsize = def_sz->vsize;
+                       dst_sz.vsize = def_sz->hsize;
+
+                       scale_pos.w = def_sz->vsize;
+                       scale_pos.h = def_sz->hsize;
+               }
+               property->config[EXYNOS_DRM_OPS_DST].pos = scale_pos;
+               property->config[EXYNOS_DRM_OPS_DST].sz = dst_sz;
+               break;
+       case IPP_CMD_OUT:
+       default:
+               ret = -EINVAL;
+               return ret;
+       }
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_IPP_PROPERTY, property);
+       if (ret)
+               fprintf(stderr,
+                       "failed to DRM_IOCTL_EXYNOS_IPP_PROPERTY : %s\n",
+                       strerror(errno));
+
+       return ret;
+}
+
+static int exynos_drm_ipp_buf(int fd, struct drm_exynos_ipp_buf *buf,
+                                       enum drm_exynos_ops_id ops_id,
+                                       enum drm_exynos_ipp_buf_ctrl ctrl,
+                                       int id,
+                                       unsigned int gem_handle)
+{
+       int ret = 0;
+
+       memset(buf, 0x00, sizeof(struct drm_exynos_ipp_buf));
+
+       buf->ops_id = ops_id;
+       buf->buf_ctrl = ctrl;
+       buf->user_data = 0;
+       buf->id = id;
+       buf->handle[EXYNOS_DRM_PLANAR_Y] = gem_handle;
+       buf->handle[EXYNOS_DRM_PLANAR_CB] = 0;
+       buf->handle[EXYNOS_DRM_PLANAR_CR] = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_IPP_BUF, buf);
+       if (ret)
+               fprintf(stderr,
+               "failed to DRM_IOCTL_EXYNOS_IPP_BUF[id:%d][ctrl:%d] : %s\n",
+               ops_id, ctrl, strerror(errno));
+       return ret;
+}
+
+static int exynos_drm_ipp_ctrl(int fd, struct drm_exynos_ipp_ctrl *ctrl,
+                               enum drm_exynos_ipp_cmd cmd, unsigned int use)
+{
+       int ret = 0;
+
+       memset(ctrl, 0x00, sizeof(struct drm_exynos_ipp_ctrl));
+
+       ctrl->cmd = cmd;
+       ctrl->use = use;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_IPP_CTRL, ctrl);
+       if (ret)
+               fprintf(stderr,
+               "failed to DRM_IOCTL_EXYNOS_IPP_CTRL[cmd:%d][use:%d] : %s\n",
+               cmd, use, strerror(errno));
+
+       return ret;
+}
+
+void fimc_m2m_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec)
+{
+       struct drm_exynos_ipp_property property;
+       struct drm_exynos_ipp_ctrl ctrl;
+       struct drm_exynos_sz def_sz = {720, 1280};
+       struct drm_exynos_ipp_buf buf1, buf2;
+       unsigned int width=720, height=1280, stride;
+       int ret, i, j, x;
+       struct drm_exynos_gem_create gem1, gem2;
+       struct drm_exynos_gem_mmap mmap1, mmap2;
+       void *usr_addr1, *usr_addr2;
+       struct timeval begin, end;
+       struct drm_gem_close args;
+       char filename[100];
+
+       /* For property */
+       ret = exynos_drm_ipp_property(fd, &property, &def_sz, IPP_CMD_M2M, EXYNOS_DRM_DEGREE_90);
+       if (ret) {
+               fprintf(stderr, "failed to ipp property\n");
+               return;
+       }
+
+       /* For mode */
+       width = height = 0;
+       for (i = 0; i < count; i++) {
+               connector_find_mode(&c[i]);
+               if (c[i].mode == NULL) continue;
+               width += c[i].mode->hdisplay;
+               if (height < c[i].mode->vdisplay) height = c[i].mode->vdisplay;
+       }
+       stride = width * 4;
+
+       /* For source buffer */
+       ret = util_gem_create_mmap(fd, &gem1, &mmap1, stride * height);
+       if (ret) {
+               fprintf(stderr, "failed to gem create mmap: %s\n",
+                                                       strerror(errno));
+               if (ret == -1) return;
+               else if (ret == -2) goto err_gem_mmap1;
+       }
+       usr_addr1 = (void *)(unsigned long)mmap1.mapped;
+
+       util_draw_buffer(usr_addr1, 1, width, height, stride, 0);
+
+       sprintf(filename, "/opt/media/fimc_m2m_src.bmp", j);
+       util_write_bmp(filename, usr_addr1, width, height);
+
+       /* For destination buffer */
+       ret = util_gem_create_mmap(fd, &gem2, &mmap2, stride * height);
+       if (ret) {
+               fprintf(stderr, "failed to gem create mmap: %s\n",
+                                                       strerror(errno));
+               if (ret == -1) goto err_gem_create2;
+               else if (ret == -2) goto err_gem_mmap2;
+       }
+       usr_addr2 = (void*)(unsigned long)mmap2.mapped;
+
+       util_draw_buffer(usr_addr2, 0, 0, 0, 0, mmap2.size);
+
+       sprintf(filename, "/opt/media/fimc_m2m_dst.bmp", j);
+       util_write_bmp(filename, usr_addr2, height, width);
+
+       /* For source buffer map to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf1, EXYNOS_DRM_OPS_SRC,
+                                       IPP_BUF_CTRL_MAP, 0, gem1.handle);
+       if (ret) {
+               fprintf(stderr, "failed to ipp buf src map\n");
+               goto err_ipp_buf_map1;
+       }
+
+       /* For destination buffer map to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST,
+                                       IPP_BUF_CTRL_MAP, 0, gem2.handle);
+       if (ret) {
+               fprintf(stderr, "failed to ipp buf dst map\n");
+               goto err_ipp_buf_map2;
+       }
+
+       for (j = 0; j < MAX_LOOP; j++) {
+               /* Start */
+               gettimeofday(&begin, NULL);
+               ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_M2M, 1);
+               if (ret) {
+                       fprintf(stderr,
+                               "failed to ipp ctrl IPP_CMD_M2M start\n");
+                       goto err_ipp_ctrl_start;
+               }
+
+               while (1) {
+                       struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+                       fd_set fds;
+
+                       FD_ZERO(&fds);
+                       FD_SET(0, &fds);
+                       FD_SET(fd, &fds);
+                       ret = select(fd + 1, &fds, NULL, NULL, &timeout);
+                       if (ret <= 0) {
+                               fprintf(stderr, "select timed out or error.\n");
+                               continue;
+                       } else if (FD_ISSET(0, &fds)) {
+                               break;
+                       }
+
+                       gettimeofday(&end, NULL);
+                       usec[j] = (end.tv_sec - begin.tv_sec) * 1000000 +
+                                               (end.tv_usec - begin.tv_usec);
+
+                       sprintf(filename, "/opt/media/fimc_m2m_%d.bmp", j);
+                       util_write_bmp(filename, usr_addr2, height, width);
+
+                       break;
+               }
+
+               /* For destination buffer queue to IPP */
+               ret = exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST,
+                                       IPP_BUF_CTRL_QUEUE, 0, gem2.handle);
+               if (ret) {
+                       fprintf(stderr, "failed to ipp buf dst queue\n");
+                       goto err_ipp_ctrl_start;
+               }
+       }
+
+       /* For source buffer unmap to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf1, EXYNOS_DRM_OPS_SRC,
+                                       IPP_BUF_CTRL_UNMAP, 0, gem1.handle);
+       if (ret) {
+               fprintf(stderr, "failed to ipp buf src unmap\n");
+               goto err_ipp_buf_unmap;
+       }
+
+       /* For destination buffer unmap to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST,
+                                       IPP_BUF_CTRL_UNMAP, 0, gem2.handle);
+       if (ret < 0) {
+               fprintf(stderr, "failed to ipp buf dst unmap\n");
+               goto err_ipp_buf_unmap;
+       }
+
+       /* Stop */
+       ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_M2M, 0);
+       if (ret) {
+               fprintf(stderr, "failed to ipp ctrl IPP_CMD_M2M stop\n");
+               goto err_ipp_buf_unmap;
+       }
+
+       munmap(usr_addr2, mmap2.size);
+       munmap(usr_addr1, mmap1.size);
+
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem2.handle;
+       exynos_gem_close(fd, &args);
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem1.handle;
+       exynos_gem_close(fd, &args);
+
+       return;
+
+err_ipp_buf_unmap:
+       exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_M2M, 0);
+err_ipp_ctrl_start:
+       exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST, IPP_BUF_CTRL_UNMAP,
+                                                               0, gem2.handle);
+err_ipp_buf_map2:
+       exynos_drm_ipp_buf(fd, &buf1, EXYNOS_DRM_OPS_SRC, IPP_BUF_CTRL_UNMAP,
+                                                               0, gem1.handle);
+err_ipp_buf_map1:
+       munmap(usr_addr2, mmap2.size);
+err_gem_mmap2:
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem2.handle;
+       exynos_gem_close(fd, &args);
+err_gem_create2:
+       munmap(usr_addr1, mmap1.size);
+err_gem_mmap1:
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem1.handle;
+       exynos_gem_close(fd, &args);
+}
+
+int fimc_event_handler(struct drm_exynos_ipp_buf *buf, struct drm_exynos_gem_create *gem,
+       void **usr_addr, unsigned int width, unsigned int height)
+{
+       char buffer[1024];
+       int len, i;
+       struct drm_event *e;
+       struct drm_exynos_ipp_event *ipp_event;
+       char filename[100];
+       int ret = 0;
+       static bmp_idx = 0;
+
+       len = read(fd, buffer, sizeof buffer);
+       if (len == 0)
+               return 0;
+       if (len < sizeof *e)
+               return -1;
+
+       i = 0;
+       while (i < len) {
+               e = (struct drm_event *) &buffer[i];
+               switch (e->type) {
+               case DRM_EXYNOS_IPP_EVENT:
+                       ipp_event = (struct drm_exynos_ipp_event *) e;
+
+                       fprintf(stderr, "%s:buf_idx[%d]bmp_idx[%d]\n", __func__, ipp_event->buf_idx, bmp_idx++);
+                       sprintf(filename, "/opt/media/fimc_wb_%d.bmp", bmp_idx);
+                       util_write_bmp(filename, usr_addr[ipp_event->buf_idx], width, height);
+
+                       /* For destination buffer queue to IPP */
+                       ret = exynos_drm_ipp_buf(fd, &buf[ipp_event->buf_idx], EXYNOS_DRM_OPS_DST,
+                                               IPP_BUF_CTRL_QUEUE, ipp_event->buf_idx, gem[ipp_event->buf_idx].handle);
+                       if (ret) {
+                               fprintf(stderr, "failed to ipp buf dst queue\n");
+                               goto err_ipp_ctrl_close;
+                       }
+                       break;
+               default:
+                       break;
+               }
+               i += e->length;
+       }
+
+err_ipp_ctrl_close:
+       return ret;
+}
+
+void fimc_wb_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec)
+{
+       struct drm_exynos_pos def_pos = {0, 0, 720, 1280};
+       struct drm_exynos_sz def_sz = {720, 1280};
+       struct drm_exynos_ipp_property property;
+       struct drm_exynos_gem_create gem[MAX_BUF];
+       struct drm_exynos_gem_mmap mmap[MAX_BUF];
+       struct drm_exynos_ipp_buf buf[MAX_BUF]; 
+       void *usr_addr[MAX_BUF];
+       struct drm_exynos_ipp_ctrl ctrl;
+       unsigned int width, height, stride;
+       int ret, i, j;
+       struct timeval begin, end;
+       struct drm_gem_close args;
+
+       /* For property */
+       ret = exynos_drm_ipp_property(fd, &property, &def_sz, IPP_CMD_WB, EXYNOS_DRM_DEGREE_0);
+       if (ret) {
+               fprintf(stderr, "failed to ipp property\n");
+               return;
+       }
+
+       /* For mode */
+       width = height = 0;
+       for (i = 0; i < count; i++) {
+               connector_find_mode(&c[i]);
+               if (c[i].mode == NULL) continue;
+               width += c[i].mode->hdisplay;
+               if (height < c[i].mode->vdisplay) height = c[i].mode->vdisplay;
+       }
+       stride = width * 4;
+
+       /* For destination buffer */
+       for (i = 0; i < MAX_BUF; i++) {
+               ret = util_gem_create_mmap(fd, &gem[i], &mmap[i], stride * height);
+               if (ret) {
+                       fprintf(stderr, "failed to gem create mmap: %s\n",
+                                                               strerror(errno));
+                       if (ret == -1) return;
+                       else if (ret == -2) goto err_ipp_ctrl_close;
+               }
+               usr_addr[i] = (void *)(unsigned long)mmap[i].mapped;
+               /* For destination buffer map to IPP */
+               ret = exynos_drm_ipp_buf(fd, &buf[i], EXYNOS_DRM_OPS_DST,
+                                               IPP_BUF_CTRL_MAP, i, gem[i].handle);
+               if (ret) {
+                       fprintf(stderr, "failed to ipp buf dst map\n");
+                       goto err_ipp_ctrl_close;
+               }
+       }
+
+
+       /* Start */
+       gettimeofday(&begin, NULL);
+       ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_WB, 1);
+       if (ret) {
+               fprintf(stderr,
+                       "failed to ipp ctrl IPP_CMD_WB start\n");
+               goto err_ipp_ctrl_close;
+       }
+
+       j = 0;
+       while (1) {
+               struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+               fd_set fds;
+
+               FD_ZERO(&fds);
+               FD_SET(0, &fds);
+               FD_SET(fd, &fds);
+               ret = select(fd + 1, &fds, NULL, NULL, &timeout);
+               if (ret <= 0) {
+                       fprintf(stderr, "select timed out or error.\n");
+                       continue;
+               } else if (FD_ISSET(0, &fds)) {
+                       fprintf(stderr, "select error.\n");
+                       break;
+               }
+
+               gettimeofday(&end, NULL);
+               usec[j] = (end.tv_sec - begin.tv_sec) * 1000000 +
+                                       (end.tv_usec - begin.tv_usec);
+
+               if (property.config[EXYNOS_DRM_OPS_DST].degree == EXYNOS_DRM_DEGREE_90 ||
+                       property.config[EXYNOS_DRM_OPS_DST].degree == EXYNOS_DRM_DEGREE_270) {
+                       if(fimc_event_handler(buf, gem, usr_addr, height, width) < 0)
+                               break;
+               } else {
+                       if(fimc_event_handler(buf, gem, usr_addr, width, height) < 0)
+                               break;
+               }
+
+               if (++j > MAX_LOOP)
+                       break;
+
+               if (j == HALF_LOOP) {
+                       /* Stop */
+                       ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_WB, 0);
+                       if (ret) {
+                               fprintf(stderr, "failed to ipp ctrl IPP_CMD_WB stop\n");
+                               goto err_ipp_ctrl_close;
+                       }
+
+                       /* For property */
+                       ret = exynos_drm_ipp_property(fd, &property, &def_sz, IPP_CMD_WB, EXYNOS_DRM_DEGREE_90);
+                       if (ret) {
+                               fprintf(stderr, "failed to ipp property\n");
+                               goto err_ipp_ctrl_close;
+                       }
+
+                       /* Start */
+                       ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_WB, 1);
+                       if (ret) {
+                               fprintf(stderr,
+                                       "failed to ipp ctrl IPP_CMD_WB start\n");
+                               goto err_ipp_ctrl_close;
+                       }
+               }
+
+               gettimeofday(&begin, NULL);
+       }
+
+err_ipp_ctrl_close:
+       /* For destination buffer unmap to IPP */
+       for (i = 0; i < MAX_BUF; i++) {
+               ret = exynos_drm_ipp_buf(fd, &buf[i], EXYNOS_DRM_OPS_DST,
+                                               IPP_BUF_CTRL_UNMAP, i, gem[i].handle);
+               if (ret < 0)
+                       fprintf(stderr, "failed to ipp buf dst unmap\n");
+       }
+
+       /* Stop */
+       ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_WB, 0);
+       if (ret)
+               fprintf(stderr, "failed to ipp ctrl IPP_CMD_WB stop\n");
+
+       for (i = 0; i < MAX_BUF; i++) {
+               munmap(usr_addr[i], mmap[i].size);
+               memset(&args, 0x00, sizeof(struct drm_gem_close));
+               args.handle = gem[i].handle;
+               exynos_gem_close(fd, &args);
+       }
+
+       return;
+}
+
+void fimc_output_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec)
+{
+       fprintf(stderr, "not supported. please wait v2\n");
+}
+
diff --git a/tests/ipptest/fimc.h b/tests/ipptest/fimc.h
new file mode 100644 (file)
index 0000000..81e0e00
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef __FIMC_H__
+#define __FIMC_H__
+
+void fimc_m2m_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec);
+void fimc_wb_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec);
+void fimc_output_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec);
+
+#endif
diff --git a/tests/ipptest/fimctest.c b/tests/ipptest/fimctest.c
new file mode 100644 (file)
index 0000000..dde9a49
--- /dev/null
@@ -0,0 +1,478 @@
+/*
+ * DRM based fimc test program
+ * Copyright 2012 Samsung Electronics
+ *   Eunchul Kim <chulspro.kim@sasmsung.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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+/*
+ * This fairly simple test program dumps output in a similar format to the
+ * "xrandr" tool everyone knows & loves.  It's necessarily slightly different
+ * since the kernel separates outputs into encoder and connector structures,
+ * each with their own unique ID.  The program also allows test testing of the
+ * memory management and mode setting APIs by allowing the user to specify a
+ * connector and mode to use for mode setting.  If all works as expected, a
+ * blue background should be painted on the monitor attached to the specified
+ * connector after the selected mode is set.
+ *
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include "libkms.h"
+
+#include "exynos_drm.h"
+
+#include "fimctest.h"
+#include "fimc.h"
+
+drmModeRes *resources;
+int fd, modes;
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct type_name {
+       int type;
+       char *name;
+};
+
+#define type_name_fn(res) \
+char * res##_str(int type) {                   \
+       int i;                                          \
+       for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
+               if (res##_names[i].type == type)        \
+                       return res##_names[i].name;     \
+       }                                               \
+       return "(invalid)";                             \
+}
+
+struct type_name encoder_type_names[] = {
+       { DRM_MODE_ENCODER_NONE, "none" },
+       { DRM_MODE_ENCODER_DAC, "DAC" },
+       { DRM_MODE_ENCODER_TMDS, "TMDS" },
+       { DRM_MODE_ENCODER_LVDS, "LVDS" },
+       { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+};
+
+type_name_fn(encoder_type)
+
+struct type_name connector_status_names[] = {
+       { DRM_MODE_CONNECTED, "connected" },
+       { DRM_MODE_DISCONNECTED, "disconnected" },
+       { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+type_name_fn(connector_status)
+
+struct type_name connector_type_names[] = {
+       { DRM_MODE_CONNECTOR_Unknown, "unknown" },
+       { DRM_MODE_CONNECTOR_VGA, "VGA" },
+       { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
+       { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
+       { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
+       { DRM_MODE_CONNECTOR_Composite, "composite" },
+       { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
+       { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
+       { DRM_MODE_CONNECTOR_Component, "component" },
+       { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
+       { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
+       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
+       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
+       { DRM_MODE_CONNECTOR_TV, "TV" },
+       { DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
+       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
+};
+
+type_name_fn(connector_type)
+
+static void dump_encoders(void)
+{
+       drmModeEncoder *encoder;
+       int i;
+
+       printf("Encoders:\n");
+       printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
+       for (i = 0; i < resources->count_encoders; i++) {
+               encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+               if (!encoder) {
+                       fprintf(stderr, "could not get encoder %i: %s\n",
+                               resources->encoders[i], strerror(errno));
+                       continue;
+               }
+               printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+                      encoder->encoder_id,
+                      encoder->crtc_id,
+                      encoder_type_str(encoder->encoder_type),
+                      encoder->possible_crtcs,
+                      encoder->possible_clones);
+               drmModeFreeEncoder(encoder);
+       }
+       printf("\n");
+}
+
+static void dump_mode(drmModeModeInfo *mode)
+{
+       printf("  %s %d %d %d %d %d %d %d %d %d\n",
+              mode->name,
+              mode->vrefresh,
+              mode->hdisplay,
+              mode->hsync_start,
+              mode->hsync_end,
+              mode->htotal,
+              mode->vdisplay,
+              mode->vsync_start,
+              mode->vsync_end,
+              mode->vtotal);
+}
+
+static void dump_props(drmModeConnector *connector)
+{
+       drmModePropertyPtr props;
+       int i;
+
+       for (i = 0; i < connector->count_props; i++) {
+               props = drmModeGetProperty(fd, connector->props[i]);
+               printf("\t%s, flags %d\n", props->name, props->flags);
+               drmModeFreeProperty(props);
+       }
+}
+
+static void dump_connectors(void)
+{
+       drmModeConnector *connector;
+       int i, j;
+
+       printf("Connectors:\n");
+       printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n");
+       for (i = 0; i < resources->count_connectors; i++) {
+               connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+               if (!connector) {
+                       fprintf(stderr, "could not get connector %i: %s\n",
+                               resources->connectors[i], strerror(errno));
+                       continue;
+               }
+
+               printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t",
+                      connector->connector_id,
+                      connector->encoder_id,
+                      connector_status_str(connector->connection),
+                      connector_type_str(connector->connector_type),
+                      connector->mmWidth, connector->mmHeight,
+                      connector->count_modes);
+
+               for (j = 0; j < connector->count_encoders; j++)
+                       printf("%s%d", j > 0 ? ", " : "",
+                                                       connector->encoders[j]);
+               printf("\n");
+
+               if (!connector->count_modes)
+                       continue;
+
+               printf("  modes:\n");
+               printf("  name refresh (Hz) hdisp hss hse htot vdisp "
+                      "vss vse vtot)\n");
+               for (j = 0; j < connector->count_modes; j++)
+                       dump_mode(&connector->modes[j]);
+
+               printf("  props:\n");
+               dump_props(connector);
+
+               drmModeFreeConnector(connector);
+       }
+       printf("\n");
+}
+
+static void dump_crtcs(void)
+{
+       drmModeCrtc *crtc;
+       int i;
+
+       printf("CRTCs:\n");
+       printf("id\tfb\tpos\tsize\n");
+       for (i = 0; i < resources->count_crtcs; i++) {
+               crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
+
+               if (!crtc) {
+                       fprintf(stderr, "could not get crtc %i: %s\n",
+                               resources->crtcs[i], strerror(errno));
+                       continue;
+               }
+               printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+                      crtc->crtc_id,
+                      crtc->buffer_id,
+                      crtc->x, crtc->y,
+                      crtc->width, crtc->height);
+               dump_mode(&crtc->mode);
+
+               drmModeFreeCrtc(crtc);
+       }
+       printf("\n");
+}
+
+static void dump_framebuffers(void)
+{
+       drmModeFB *fb;
+       int i;
+
+       printf("Frame buffers:\n");
+       printf("id\tsize\tpitch\n");
+       for (i = 0; i < resources->count_fbs; i++) {
+               fb = drmModeGetFB(fd, resources->fbs[i]);
+
+               if (!fb) {
+                       fprintf(stderr, "could not get fb %i: %s\n",
+                               resources->fbs[i], strerror(errno));
+                       continue;
+               }
+               printf("%u\t(%ux%u)\t%u\n",
+                      fb->fb_id,
+                      fb->width, fb->height,
+                      fb->pitch);
+
+               drmModeFreeFB(fb);
+       }
+       printf("\n");
+}
+
+/*
+ * Mode setting with the kernel interfaces is a bit of a chore.
+ * First you have to find the connector in question and make sure the
+ * requested mode is available.
+ * Then you need to find the encoder attached to that connector so you
+ * can bind it with a free crtc.
+ */
+
+void connector_find_mode(struct connector *c)
+{
+       drmModeConnector *connector;
+       int i, j;
+
+       /* First, find the connector & mode */
+       c->mode = NULL;
+       for (i = 0; i < resources->count_connectors; i++) {
+               connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+               if (!connector) {
+                       fprintf(stderr, "could not get connector %i: %s\n",
+                               resources->connectors[i], strerror(errno));
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (!connector->count_modes) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (connector->connector_id != c->id) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               for (j = 0; j < connector->count_modes; j++) {
+                       c->mode = &connector->modes[j];
+                       if (!strcmp(c->mode->name, c->mode_str))
+                               break;
+               }
+
+               /* Found it, break out */
+               if (c->mode)
+                       break;
+
+               drmModeFreeConnector(connector);
+       }
+
+       if (!c->mode) {
+               fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
+               return;
+       }
+
+       /* Now get the encoder */
+       for (i = 0; i < resources->count_encoders; i++) {
+               c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+               if (!c->encoder) {
+                       fprintf(stderr, "could not get encoder %i: %s\n",
+                               resources->encoders[i], strerror(errno));
+                       drmModeFreeEncoder(c->encoder);
+                       continue;
+               }
+
+               if (c->encoder->encoder_id  == connector->encoder_id)
+                       break;
+
+               drmModeFreeEncoder(c->encoder);
+       }
+
+       if (c->crtc == -1)
+               c->crtc = c->encoder->crtc_id;
+}
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "ecpmfo:s:v";
+
+static void usage(char *name)
+{
+       fprintf(stderr, "usage: %s [-ecpmf]\n", name);
+       fprintf(stderr, "\t-e\tlist encoders\n");
+       fprintf(stderr, "\t-c\tlist connectors\n");
+       fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
+       fprintf(stderr, "\t-m\tlist modes\n");
+       fprintf(stderr, "\t-f\tlist framebuffers\n");
+       fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
+       fprintf(stderr, "\t-o\tlist of operation id : 0: M2M, 1: Writeback, 2: Output\n");
+       fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\n\tDefault is to dump all info.\n");
+       exit(0);
+}
+
+#define dump_resource(res) if (res) dump_##res()
+
+int main(int argc, char **argv)
+{
+       int c;
+       int operations = 0, encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
+       int test_vsync = 0;
+       char *modules[] = {"exynos", "i915", "radeon", "nouveau", "vmwgfx"};
+       char *modeset = NULL;
+       int i, count = 0;
+       struct connector con_args[2];
+       
+       opterr = 0;
+       while ((c = getopt(argc, argv, optstr)) != -1) {
+               switch (c) {
+               case 'e':
+                       encoders = 1;
+                       break;
+               case 'c':
+                       connectors = 1;
+                       break;
+               case 'p':
+                       crtcs = 1;
+                       break;
+               case 'm':
+                       modes = 1;
+                       break;
+               case 'f':
+                       framebuffers = 1;
+                       break;
+               case 'v':
+                       test_vsync = 1;
+                       break;
+               case 'o':
+                       if (optarg)
+                               sscanf(optarg, "%d", &operations);
+                       break;
+               case 's':
+                       modeset = strdup(optarg);
+                       con_args[count].crtc = -1;
+                       if (sscanf(optarg, "%d:%64s",
+                                  &con_args[count].id,
+                                  con_args[count].mode_str) != 2 &&
+                           sscanf(optarg, "%d@%d:%64s",
+                                  &con_args[count].id,
+                                  &con_args[count].crtc,
+                                  con_args[count].mode_str) != 3)
+                               usage(argv[0]);
+                       count++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       if (argc == 1)
+               encoders = connectors = crtcs = modes = framebuffers = 1;
+
+       for (i = 0; i < ARRAY_SIZE(modules); i++) {
+               printf("trying to load module %s...", modules[i]);
+               fd = drmOpen(modules[i], NULL);
+               if (fd < 0) {
+                       printf("failed.\n");
+               } else {
+                       printf("success.\n");
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(modules)) {
+               fprintf(stderr, "failed to load any modules, aborting.\n");
+               return -1;
+       }
+
+       resources = drmModeGetResources(fd);
+       if (!resources) {
+               fprintf(stderr, "drmModeGetResources failed: %s\n",
+                       strerror(errno));
+               drmClose(fd);
+               return 1;
+       }
+
+       dump_resource(encoders);
+       dump_resource(connectors);
+       dump_resource(crtcs);
+       dump_resource(framebuffers);
+
+       if (count > 0) {
+               long int sum = 0, usec[MAX_LOOP];
+
+               switch(operations) {
+               case 0:
+                       fimc_m2m_set_mode(con_args, count, test_vsync, usec);
+                       break;
+               case 1:
+                       fimc_wb_set_mode(con_args, count, test_vsync, usec);
+                       break;
+               case 2:
+                       fimc_output_set_mode(con_args, count, test_vsync, usec);
+                       break;
+               default:
+                       break;
+               }
+
+               for (i = 0; i < MAX_LOOP; i++) {
+                       printf("[%d] : %d\n", i + 1, usec[i]);
+                       sum += usec[i];
+               }
+               printf("fimc : cma\n");
+               printf("avg : [%d]\n", sum / MAX_LOOP);
+               getchar();
+       }
+
+       drmModeFreeResources(resources);
+
+       return 0;
+}
diff --git a/tests/ipptest/fimctest.h b/tests/ipptest/fimctest.h
new file mode 100644 (file)
index 0000000..2dd31fa
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef __FIMCTEST_H__
+#define __FIMCTEST_H__
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#define MAX_LOOP 20
+#define HALF_LOOP 10
+#define MAX_BUF 3
+
+struct connector {
+       uint32_t id;
+       char mode_str[64];
+       drmModeModeInfo *mode;
+       drmModeEncoder *encoder;
+       int crtc;
+       unsigned int fb_id[2], current_fb_id;
+       struct timeval start;
+
+       int swap_count;
+};
+
+extern int fd;
+
+extern void connector_find_mode(struct connector *c);
+
+#endif
diff --git a/tests/ipptest/gem.c b/tests/ipptest/gem.c
new file mode 100644 (file)
index 0000000..40f192a
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * DRM based fimc test program
+ * Copyright 2012 Samsung Electronics
+ *   Eunchul Kim <chulspro.kim@sasmsung.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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "libkms.h"
+
+#include "exynos_drm.h"
+
+int exynos_gem_create(int fd, struct drm_exynos_gem_create *gem)
+{
+       int ret = 0;
+
+       if (!gem) {
+               fprintf(stderr, "gem object is null.\n");
+               return -EFAULT;
+       }
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CREATE, gem);
+       if (ret < 0)
+               fprintf(stderr, "failed to create gem buffer: %s\n",
+                                                               strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_userptr(int fd, struct drm_exynos_gem_userptr *gem_userptr)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_USERPTR, gem_userptr);
+       if (ret < 0)
+               fprintf(stderr, "failed to userptr: %s\n", strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_MMAP, in_mmap);
+       if (ret < 0)
+               fprintf(stderr, "failed to mmap: %s\n", strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_close(int fd, struct drm_gem_close *gem_close)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, gem_close);
+       if (ret < 0)
+               fprintf(stderr, "failed to close: %s\n", strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_cache_op(int fd, struct drm_exynos_gem_cache_op *cache_op)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CACHE_OP, cache_op);
+       if (ret < 0)
+               fprintf(stderr, "failed to cache op: %s\n", strerror(-ret));
+       return ret;
+}
diff --git a/tests/ipptest/gem.h b/tests/ipptest/gem.h
new file mode 100644 (file)
index 0000000..2a5ed1d
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __GEM_H__
+#define __GEM_H__
+
+extern int exynos_gem_create(int fd, struct drm_exynos_gem_create *gem);
+extern int exynos_gem_userptr(int fd,
+                               struct drm_exynos_gem_userptr *gem_userptr);
+extern int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap);
+extern int exynos_gem_close(int fd, struct drm_gem_close *gem_close);
+extern int exynos_gem_cache_op(int fd,
+                               struct drm_exynos_gem_cache_op *cache_op);
+
+#endif
diff --git a/tests/ipptest/util.c b/tests/ipptest/util.c
new file mode 100644 (file)
index 0000000..745c212
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * DRM based fimc test program
+ * Copyright 2012 Samsung Electronics
+ *   Eunchul Kim <chulspro.kim@sasmsung.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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "exynos_drm.h"
+#include "gem.h"
+
+int util_gem_create_mmap(int fd, struct drm_exynos_gem_create *gem,
+                                       struct drm_exynos_gem_mmap *mmap,
+                                       unsigned int size)
+{
+       /* initialize structure for gem create */
+       memset(gem, 0x00, sizeof(struct drm_exynos_gem_create));
+       gem->size = size;
+
+       if (exynos_gem_create(fd, gem) < 0) {
+               fprintf(stderr, "failed to gem create: %s\n", strerror(errno));
+               return -1;
+       }
+
+       /* initialize structure for gem mmap */
+       memset(mmap, 0x00, sizeof(struct drm_exynos_gem_mmap));
+       mmap->handle = gem->handle;
+       mmap->size = gem->size;
+
+       if (exynos_gem_mmap(fd, mmap) < 0) {
+               fprintf(stderr, "failed to gem mmap: %s\n", strerror(errno));
+               return -2;
+       }
+
+       return 0;
+}
+
+void util_draw_buffer(void *addr, unsigned int stripe,
+                               unsigned int width, unsigned int height,
+                               unsigned int stride, unsigned int size)
+{
+       if (stripe == 1) {
+               int i, j;
+               unsigned int *fb_ptr;
+               div_t d;
+
+               for (j = 0; j < height; j++) {
+                       fb_ptr = (unsigned int *)((char *)addr + j * stride);
+                       for (i = 0; i < width; i++) {
+                               d = div(i, width);
+                               fb_ptr[i] = 0x00130502 * (d.quot >> 6)
+                                               + 0x000a1120 * (d.rem >> 6);
+                       }
+               }
+       } else
+               memset(addr, 0x77, size);
+}
+
+int util_write_bmp(const char *file, const void *data, unsigned int width,
+                                                       unsigned int height)
+{
+       int i;
+       unsigned int * blocks;
+       FILE *fp;
+       struct {
+               unsigned char magic[2];
+       } bmpfile_magic = { {'B', 'M'} };
+       struct {
+               unsigned int filesz;
+               unsigned short creator1;
+               unsigned short creator2;
+               unsigned int bmp_offset;
+       } bmpfile_header = { 0, 0, 0, 0x36 };
+       struct {
+               unsigned int header_sz;
+               unsigned int width;
+               unsigned int height;
+               unsigned short nplanes;
+               unsigned short bitspp;
+               unsigned int compress_type;
+               unsigned int bmp_bytesz;
+               unsigned int hres;
+               unsigned int vres;
+               unsigned int ncolors;
+               unsigned int nimpcolors;
+       } bmp_dib_v3_header_t = { 0x28, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0 };
+
+       fp = fopen(file, "wb");
+       if (fp == NULL) return -1;
+
+       bmpfile_header.filesz = sizeof(bmpfile_magic) + sizeof(bmpfile_header)
+                       + sizeof(bmp_dib_v3_header_t) + width * height * 4;
+       bmp_dib_v3_header_t.header_sz = sizeof(bmp_dib_v3_header_t);
+       bmp_dib_v3_header_t.width = width;
+       bmp_dib_v3_header_t.height = -height;
+       bmp_dib_v3_header_t.nplanes = 1;
+       bmp_dib_v3_header_t.bmp_bytesz = width * height * 4;
+
+       fwrite(&bmpfile_magic, sizeof(bmpfile_magic), 1, fp);
+       fwrite(&bmpfile_header, sizeof(bmpfile_header), 1, fp);
+       fwrite(&bmp_dib_v3_header_t, sizeof(bmp_dib_v3_header_t), 1, fp);
+
+       blocks = (unsigned int*)data;
+       for (i = 0; i < height * width; i++)
+               fwrite(&blocks[i], 4, 1, fp);
+
+       fclose(fp);
+       return 0;
+}
diff --git a/tests/ipptest/util.h b/tests/ipptest/util.h
new file mode 100644 (file)
index 0000000..e1ffcca
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __UTIL_H__
+#define __UTIL_H__
+
+extern int util_gem_create_mmap(int fd, struct drm_exynos_gem_create *gem,
+                                       struct drm_exynos_gem_mmap *mmap,
+                                       unsigned int size);
+extern void util_draw_buffer(void *addr, unsigned int stripe,
+                               unsigned int width, unsigned int height,
+                               unsigned int stride, unsigned int size);
+extern int util_write_bmp(const char *file, const void *data,
+                               unsigned int width, unsigned int height);
+#endif
index ea39685..2191242 100644 (file)
@@ -1,7 +1,6 @@
 AM_CFLAGS = \
        -I$(top_srcdir)/include/drm \
        -I$(top_srcdir)/libkms/ \
-       -I$(top_srcdir)/slp/ \
        -I$(top_srcdir) \
        $(CAIRO_CFLAGS)
 
@@ -13,5 +12,4 @@ modetest_SOURCES = \
 modetest_LDADD = \
        $(top_builddir)/libdrm.la \
        $(top_builddir)/libkms/libkms.la \
-       $(top_builddir)/slp/libdrm_slp.la \
        $(CAIRO_LIBS)
old mode 100755 (executable)
new mode 100644 (file)
index 0c49ad7..dc84cf3
@@ -43,6 +43,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
+#include <inttypes.h>
 #include <unistd.h>
 #include <string.h>
 #include <errno.h>
 
 #include "xf86drm.h"
 #include "xf86drmMode.h"
+#include "drm_fourcc.h"
 #include "libkms.h"
 
-#define TEST_SLP
-#ifdef TEST_SLP
-#include "drm_slp_bufmgr.h"
-#include "exynos_drm.h"
-
-static drm_slp_bufmgr slp_bufmgr=NULL;
-#endif
-
 #ifdef HAVE_CAIRO
 #include <math.h>
 #include <cairo.h>
@@ -78,7 +72,7 @@ struct type_name {
 
 #define type_name_fn(res) \
 char * res##_str(int type) {                   \
-       int i;                                          \
+       unsigned int i;                                 \
        for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
                if (res##_names[i].type == type)        \
                        return res##_names[i].name;     \
@@ -152,7 +146,7 @@ void dump_encoders(void)
 
 void dump_mode(drmModeModeInfo *mode)
 {
-       printf("  %s %d %d %d %d %d %d %d %d %d\n",
+       printf("\t%s %d %d %d %d %d %d %d %d %d\n",
               mode->name,
               mode->vrefresh,
               mode->hdisplay,
@@ -166,16 +160,98 @@ void dump_mode(drmModeModeInfo *mode)
 }
 
 static void
-dump_props(drmModeConnector *connector)
+dump_blob(uint32_t blob_id)
+{
+       uint32_t i;
+       unsigned char *blob_data;
+       drmModePropertyBlobPtr blob;
+
+       blob = drmModeGetPropertyBlob(fd, blob_id);
+       if (!blob)
+               return;
+
+       blob_data = blob->data;
+
+       for (i = 0; i < blob->length; i++) {
+               if (i % 16 == 0)
+                       printf("\n\t\t\t");
+               printf("%.2hhx", blob_data[i]);
+       }
+       printf("\n");
+
+       drmModeFreePropertyBlob(blob);
+}
+
+static void
+dump_prop(uint32_t prop_id, uint64_t value)
 {
-       drmModePropertyPtr props;
        int i;
+       drmModePropertyPtr prop;
+
+       prop = drmModeGetProperty(fd, prop_id);
 
-       for (i = 0; i < connector->count_props; i++) {
-               props = drmModeGetProperty(fd, connector->props[i]);
-               printf("\t%s, flags %d\n", props->name, props->flags);
-               drmModeFreeProperty(props);
+       printf("\t%d", prop_id);
+       if (!prop) {
+               printf("\n");
+               return;
        }
+
+       printf(" %s:\n", prop->name);
+
+       printf("\t\tflags:");
+       if (prop->flags & DRM_MODE_PROP_PENDING)
+               printf(" pending");
+       if (prop->flags & DRM_MODE_PROP_RANGE)
+               printf(" range");
+       if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
+               printf(" immutable");
+       if (prop->flags & DRM_MODE_PROP_ENUM)
+               printf(" enum");
+       if (prop->flags & DRM_MODE_PROP_BITMASK)
+               printf(" bitmask");
+       if (prop->flags & DRM_MODE_PROP_BLOB)
+               printf(" blob");
+       printf("\n");
+
+       if (prop->flags & DRM_MODE_PROP_RANGE) {
+               printf("\t\tvalues:");
+               for (i = 0; i < prop->count_values; i++)
+                       printf(" %"PRIu64, prop->values[i]);
+               printf("\n");
+       }
+
+       if (prop->flags & DRM_MODE_PROP_ENUM) {
+               printf("\t\tenums:");
+               for (i = 0; i < prop->count_enums; i++)
+                       printf(" %s=%llu", prop->enums[i].name,
+                              prop->enums[i].value);
+               printf("\n");
+       } else if (prop->flags & DRM_MODE_PROP_BITMASK) {
+               printf("\t\tvalues:");
+               for (i = 0; i < prop->count_enums; i++)
+                       printf(" %s=0x%llx", prop->enums[i].name,
+                              (1LL << prop->enums[i].value));
+               printf("\n");
+       } else {
+               assert(prop->count_enums == 0);
+       }
+
+       if (prop->flags & DRM_MODE_PROP_BLOB) {
+               printf("\t\tblobs:\n");
+               for (i = 0; i < prop->count_blobs; i++)
+                       dump_blob(prop->blob_ids[i]);
+               printf("\n");
+       } else {
+               assert(prop->count_blobs == 0);
+       }
+
+       printf("\t\tvalue:");
+       if (prop->flags & DRM_MODE_PROP_BLOB)
+               dump_blob(value);
+       else
+               printf(" %"PRIu64"\n", value);
+
+       drmModeFreeProperty(prop);
 }
 
 void dump_connectors(void)
@@ -206,17 +282,18 @@ void dump_connectors(void)
                        printf("%s%d", j > 0 ? ", " : "", connector->encoders[j]);
                printf("\n");
 
-               if (!connector->count_modes)
-                       continue;
-
-               printf("  modes:\n");
-               printf("  name refresh (Hz) hdisp hss hse htot vdisp "
-                      "vss vse vtot)\n");
-               for (j = 0; j < connector->count_modes; j++)
-                       dump_mode(&connector->modes[j]);
-
-               printf("  props:\n");
-               dump_props(connector);
+               if (connector->count_modes) {
+                       printf("  modes:\n");
+                       printf("\tname refresh (Hz) hdisp hss hse htot vdisp "
+                              "vss vse vtot)\n");
+                       for (j = 0; j < connector->count_modes; j++)
+                               dump_mode(&connector->modes[j]);
+
+                       printf("  props:\n");
+                       for (j = 0; j < connector->count_props; j++)
+                               dump_prop(connector->props[j],
+                                         connector->prop_values[j]);
+               }
 
                drmModeFreeConnector(connector);
        }
@@ -226,7 +303,9 @@ void dump_connectors(void)
 void dump_crtcs(void)
 {
        drmModeCrtc *crtc;
+       drmModeObjectPropertiesPtr props;
        int i;
+       uint32_t j;
 
        printf("CRTCs:\n");
        printf("id\tfb\tpos\tsize\n");
@@ -245,6 +324,19 @@ void dump_crtcs(void)
                       crtc->width, crtc->height);
                dump_mode(&crtc->mode);
 
+               printf("  props:\n");
+               props = drmModeObjectGetProperties(fd, crtc->crtc_id,
+                                                  DRM_MODE_OBJECT_CRTC);
+               if (props) {
+                       for (j = 0; j < props->count_props; j++)
+                               dump_prop(props->props[j],
+                                         props->prop_values[j]);
+                       drmModeFreeObjectProperties(props);
+               } else {
+                       printf("\tcould not get crtc properties: %s\n",
+                              strerror(errno));
+               }
+
                drmModeFreeCrtc(crtc);
        }
        printf("\n");
@@ -275,6 +367,64 @@ void dump_framebuffers(void)
        printf("\n");
 }
 
+static void dump_planes(void)
+{
+       drmModeObjectPropertiesPtr props;
+       drmModePlaneRes *plane_resources;
+       drmModePlane *ovr;
+       unsigned int i, j;
+
+       plane_resources = drmModeGetPlaneResources(fd);
+       if (!plane_resources) {
+               fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
+                       strerror(errno));
+               return;
+       }
+
+       printf("Planes:\n");
+       printf("id\tcrtc\tfb\tCRTC x,y\tx,y\tgamma size\n");
+       for (i = 0; i < plane_resources->count_planes; i++) {
+               ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
+               if (!ovr) {
+                       fprintf(stderr, "drmModeGetPlane failed: %s\n",
+                               strerror(errno));
+                       continue;
+               }
+
+               printf("%d\t%d\t%d\t%d,%d\t\t%d,%d\t%d\n",
+                      ovr->plane_id, ovr->crtc_id, ovr->fb_id,
+                      ovr->crtc_x, ovr->crtc_y, ovr->x, ovr->y,
+                      ovr->gamma_size);
+
+               if (!ovr->count_formats)
+                       continue;
+
+               printf("  formats:");
+               for (j = 0; j < ovr->count_formats; j++)
+                       printf(" %4.4s", (char *)&ovr->formats[j]);
+               printf("\n");
+
+               printf("  props:\n");
+               props = drmModeObjectGetProperties(fd, ovr->plane_id,
+                                                  DRM_MODE_OBJECT_PLANE);
+               if (props) {
+                       for (j = 0; j < props->count_props; j++)
+                               dump_prop(props->props[j],
+                                         props->prop_values[j]);
+                       drmModeFreeObjectProperties(props);
+               } else {
+                       printf("\tcould not get plane properties: %s\n",
+                              strerror(errno));
+               }
+
+               drmModeFreePlane(ovr);
+       }
+       printf("\n");
+
+       drmModeFreePlaneResources(plane_resources);
+       return;
+}
+
 /*
  * Mode setting with the kernel interfaces is a bit of a chore.
  * First you have to find the connector in question and make sure the
@@ -288,11 +438,19 @@ struct connector {
        drmModeModeInfo *mode;
        drmModeEncoder *encoder;
        int crtc;
+       int pipe;
        unsigned int fb_id[2], current_fb_id;
        struct timeval start;
 
        int swap_count;
-};     
+};
+
+struct plane {
+       uint32_t con_id;  /* the id of connector to bind to */
+       uint32_t w, h;
+       unsigned int fb_id;
+       char format_str[5]; /* need to leave room for terminating \0 */
+};
 
 static void
 connector_find_mode(struct connector *c)
@@ -359,6 +517,15 @@ connector_find_mode(struct connector *c)
 
        if (c->crtc == -1)
                c->crtc = c->encoder->crtc_id;
+
+       /* and figure out which crtc index it is: */
+       for (i = 0; i < resources->count_crtcs; i++) {
+               if (c->crtc == resources->crtcs[i]) {
+                       c->pipe = i;
+                       break;
+               }
+       }
+
 }
 
 static struct kms_bo *
@@ -441,26 +608,6 @@ make_pwetty(void *data, int width, int height, int stride)
 #endif
 }
 
-#ifdef TEST_SLP
-static drm_slp_bo
-make_drmbuf_from_kms(struct kms_bo* bo)
-{
-       unsigned int hKms;
-       drm_slp_bo drmBo = NULL;
-
-       kms_bo_get_prop(bo, KMS_HANDLE, &hKms);
-       drmBo = drm_slp_bo_attach(slp_bufmgr, NULL, NULL, 0, &hKms);
-       if(!drmBo)
-       {
-               fprintf(stderr, "Fail attach\n");
-               return drmBo;
-       }
-
-       fprintf(stderr, "DRM_BO(%p) from KMS(%p, %d)\n", drmBo, bo, hKms);
-       return drmBo;
-}
-#endif
-
 static int
 create_test_buffer(struct kms_driver *kms,
                   int width, int height, int *stride_out,
@@ -469,19 +616,11 @@ create_test_buffer(struct kms_driver *kms,
        struct kms_bo *bo;
        int ret, i, j, stride;
        void *virtual;
-#ifdef TEST_SLP
-       drm_slp_bo drmBo;
-#endif
-
 
        bo = allocate_buffer(kms, width, height, &stride);
        if (!bo)
                return -1;
 
-#ifdef TEST_SLP
-       drmBo = make_drmbuf_from_kms(bo);
-       virtual = drm_slp_bo_map(drmBo, DRM_SLP_DEVICE_CPU, DRM_SLP_OPTION_READ|DRM_SLP_OPTION_WRITE);
-#else
        ret = kms_bo_map(bo, &virtual);
        if (ret) {
                fprintf(stderr, "failed to map buffer: %s\n",
@@ -489,7 +628,6 @@ create_test_buffer(struct kms_driver *kms,
                kms_bo_destroy(&bo);
                return -1;
        }
-#endif
 
        /* paint the buffer with colored tiles */
        for (j = 0; j < height; j++) {
@@ -504,11 +642,7 @@ create_test_buffer(struct kms_driver *kms,
 
        make_pwetty(virtual, width, height, stride);
 
-#ifdef TEST_SLP
-       drm_slp_bo_unmap(drmBo, DRM_SLP_DEVICE_CPU);
-#else
        kms_bo_unmap(bo);
-#endif
 
        *bo_out = bo;
        *stride_out = stride;
@@ -575,13 +709,245 @@ page_flip_handler(int fd, unsigned int frame,
        }
 }
 
+/* swap these for big endian.. */
+#define RED   2
+#define GREEN 1
+#define BLUE  0
+
+static void
+fill420(unsigned char *y, unsigned char *u, unsigned char *v,
+               int cs /*chroma pixel stride */,
+               int n, int width, int height, int stride)
+{
+       int i, j;
+
+       /* paint the buffer with colored tiles, in blocks of 2x2 */
+       for (j = 0; j < height; j+=2) {
+               unsigned char *y1p = y + j * stride;
+               unsigned char *y2p = y1p + stride;
+               unsigned char *up = u + (j/2) * stride * cs / 2;
+               unsigned char *vp = v + (j/2) * stride * cs / 2;
+
+               for (i = 0; i < width; i+=2) {
+                       div_t d = div(n+i+j, width);
+                       uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
+                       unsigned char *rgbp = (unsigned char *)&rgb;
+                       unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);
+
+                       *(y2p++) = *(y1p++) = y;
+                       *(y2p++) = *(y1p++) = y;
+
+                       *up = (rgbp[BLUE] - y) * 0.565 + 128;
+                       *vp = (rgbp[RED] - y) * 0.713 + 128;
+                       up += cs;
+                       vp += cs;
+               }
+       }
+}
+
 static void
-set_mode(struct connector *c, int count, int page_flip)
+fill422(unsigned char *virtual, int n, int width, int height, int stride)
+{
+       int i, j;
+       /* paint the buffer with colored tiles */
+       for (j = 0; j < height; j++) {
+               uint8_t *ptr = (uint8_t*)((char*)virtual + j * stride);
+               for (i = 0; i < width; i++) {
+                       div_t d = div(n+i+j, width);
+                       uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
+                       unsigned char *rgbp = (unsigned char *)&rgb;
+                       unsigned char y = (0.299 * rgbp[RED]) + (0.587 * rgbp[GREEN]) + (0.114 * rgbp[BLUE]);
+
+                       *(ptr++) = y;
+                       *(ptr++) = (rgbp[BLUE] - y) * 0.565 + 128;
+                       *(ptr++) = y;
+                       *(ptr++) = (rgbp[RED] - y) * 0.713 + 128;
+               }
+       }
+}
+
+static void
+fill1555(unsigned char *virtual, int n, int width, int height, int stride)
+{
+       int i, j;
+       /* paint the buffer with colored tiles */
+       for (j = 0; j < height; j++) {
+               uint16_t *ptr = (uint16_t*)((char*)virtual + j * stride);
+               for (i = 0; i < width; i++) {
+                       div_t d = div(n+i+j, width);
+                       uint32_t rgb = 0x00130502 * (d.quot >> 6) + 0x000a1120 * (d.rem >> 6);
+                       unsigned char *rgbp = (unsigned char *)&rgb;
+
+                       *(ptr++) = 0x8000 |
+                                       (rgbp[RED] >> 3) << 10 |
+                                       (rgbp[GREEN] >> 3) << 5 |
+                                       (rgbp[BLUE] >> 3);
+               }
+       }
+}
+
+static int
+set_plane(struct kms_driver *kms, struct connector *c, struct plane *p)
+{
+       drmModePlaneRes *plane_resources;
+       drmModePlane *ovr;
+       uint32_t handles[4], pitches[4], offsets[4] = {0}; /* we only use [0] */
+       uint32_t plane_id = 0;
+       struct kms_bo *plane_bo;
+       uint32_t plane_flags = 0, format;
+       int ret, crtc_x, crtc_y, crtc_w, crtc_h;
+       unsigned int i;
+
+       /* find an unused plane which can be connected to our crtc */
+       plane_resources = drmModeGetPlaneResources(fd);
+       if (!plane_resources) {
+               fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
+                       strerror(errno));
+               return -1;
+       }
+
+       for (i = 0; i < plane_resources->count_planes && !plane_id; i++) {
+               ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
+               if (!ovr) {
+                       fprintf(stderr, "drmModeGetPlane failed: %s\n",
+                               strerror(errno));
+                       return -1;
+               }
+
+               if ((ovr->possible_crtcs & (1 << c->pipe)) && !ovr->crtc_id)
+                       plane_id = ovr->plane_id;
+
+               drmModeFreePlane(ovr);
+       }
+
+       fprintf(stderr, "testing %dx%d@%s overlay plane\n",
+                       p->w, p->h, p->format_str);
+
+       if (!plane_id) {
+               fprintf(stderr, "failed to find plane!\n");
+               return -1;
+       }
+
+       if (!strcmp(p->format_str, "XR24")) {
+               if (create_test_buffer(kms, p->w, p->h, &pitches[0], &plane_bo))
+                       return -1;
+               kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
+               format = DRM_FORMAT_XRGB8888;
+       } else {
+               void *virtual;
+
+               /* TODO: this always allocates a buffer for 32bpp RGB.. but for
+                * YUV formats, we don't use all of it..  since 4bytes/pixel is
+                * worst case, so live with it for now and just don't use all
+                * the buffer:
+                */
+               plane_bo = allocate_buffer(kms, p->w, p->h, &pitches[0]);
+               if (!plane_bo)
+                       return -1;
+
+               ret = kms_bo_map(plane_bo, &virtual);
+               if (ret) {
+                       fprintf(stderr, "failed to map buffer: %s\n",
+                               strerror(-ret));
+                       kms_bo_destroy(&plane_bo);
+                       return -1;
+               }
+
+               /* just testing a limited # of formats to test single
+                * and multi-planar path.. would be nice to add more..
+                */
+               if (!strcmp(p->format_str, "YUYV")) {
+                       pitches[0] = p->w * 2;
+                       offsets[0] = 0;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
+
+                       fill422(virtual, 0, p->w, p->h, pitches[0]);
+
+                       format = DRM_FORMAT_YUYV;
+               } else if (!strcmp(p->format_str, "NV12")) {
+                       pitches[0] = p->w;
+                       offsets[0] = 0;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
+                       pitches[1] = p->w;
+                       offsets[1] = p->w * p->h;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]);
+
+                       fill420(virtual, virtual+offsets[1], virtual+offsets[1]+1,
+                                       2, 0, p->w, p->h, pitches[0]);
+
+                       format = DRM_FORMAT_NV12;
+               } else if (!strcmp(p->format_str, "YV12")) {
+                       pitches[0] = p->w;
+                       offsets[0] = 0;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
+                       pitches[1] = p->w / 2;
+                       offsets[1] = p->w * p->h;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[1]);
+                       pitches[2] = p->w / 2;
+                       offsets[2] = offsets[1] + (p->w * p->h) / 4;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[2]);
+
+                       fill420(virtual, virtual+offsets[1], virtual+offsets[2],
+                                       1, 0, p->w, p->h, pitches[0]);
+
+                       format = DRM_FORMAT_YVU420;
+               } else if (!strcmp(p->format_str, "XR15")) {
+                       pitches[0] = p->w * 2;
+                       offsets[0] = 0;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
+
+                       fill1555(virtual, 0, p->w, p->h, pitches[0]);
+
+                       format = DRM_FORMAT_XRGB1555;
+               } else if (!strcmp(p->format_str, "AR15")) {
+                       pitches[0] = p->w * 2;
+                       offsets[0] = 0;
+                       kms_bo_get_prop(plane_bo, KMS_HANDLE, &handles[0]);
+
+                       fill1555(virtual, 0, p->w, p->h, pitches[0]);
+
+                       format = DRM_FORMAT_ARGB1555;
+               } else {
+                       fprintf(stderr, "Unknown format: %s\n", p->format_str);
+                       return -1;
+               }
+
+               kms_bo_unmap(plane_bo);
+       }
+
+       /* just use single plane format for now.. */
+       if (drmModeAddFB2(fd, p->w, p->h, format,
+                       handles, pitches, offsets, &p->fb_id, plane_flags)) {
+               fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
+               return -1;
+       }
+
+       /* ok, boring.. but for now put in middle of screen: */
+       crtc_x = c->mode->hdisplay / 3;
+       crtc_y = c->mode->vdisplay / 3;
+       crtc_w = crtc_x;
+       crtc_h = crtc_y;
+
+       /* note src coords (last 4 args) are in Q16 format */
+       if (drmModeSetPlane(fd, plane_id, c->crtc, p->fb_id,
+                           plane_flags, crtc_x, crtc_y, crtc_w, crtc_h,
+                           0, 0, p->w << 16, p->h << 16)) {
+               fprintf(stderr, "failed to enable plane: %s\n",
+                       strerror(errno));
+               return -1;
+       }
+
+       return 0;
+}
+
+static void
+set_mode(struct connector *c, int count, struct plane *p, int plane_count,
+               int page_flip)
 {
        struct kms_driver *kms;
        struct kms_bo *bo, *other_bo;
        unsigned int fb_id, other_fb_id;
-       int i, ret, width, height, x, stride;
+       int i, j, ret, width, height, x, stride;
        unsigned handle;
        drmEventContext evctx;
 
@@ -603,15 +969,6 @@ set_mode(struct connector *c, int count, int page_flip)
                return;
        }
 
-#ifdef TEST_SLP
-       slp_bufmgr = drm_slp_bufmgr_init(fd, NULL);
-       if(!slp_bufmgr)
-       {
-               fprintf(stderr, "failed to make slp_bufmgr\n");
-               return;
-       }
-#endif
-
        if (create_test_buffer(kms, width, height, &stride, &bo))
                return;
 
@@ -643,6 +1000,12 @@ set_mode(struct connector *c, int count, int page_flip)
                        fprintf(stderr, "failed to set mode: %s\n", strerror(errno));
                        return;
                }
+
+               /* if we have a plane/overlay to show, set that up now: */
+               for (j = 0; j < plane_count; j++)
+                       if (p[j].con_id == c[i].id)
+                               if (set_plane(kms, &c[i], &p[j]))
+                                       return;
        }
 
        if (!page_flip)
@@ -726,26 +1089,28 @@ set_mode(struct connector *c, int count, int page_flip)
 
 extern char *optarg;
 extern int optind, opterr, optopt;
-static char optstr[] = "ecpmfs:v";
+static char optstr[] = "ecpmfs:P:v";
 
 void usage(char *name)
 {
        fprintf(stderr, "usage: %s [-ecpmf]\n", name);
        fprintf(stderr, "\t-e\tlist encoders\n");
        fprintf(stderr, "\t-c\tlist connectors\n");
-       fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
+       fprintf(stderr, "\t-p\tlist CRTCs and planes (pipes)\n");
        fprintf(stderr, "\t-m\tlist modes\n");
        fprintf(stderr, "\t-f\tlist framebuffers\n");
        fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
        fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
        fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\t-P <connector_id>:<w>x<h>\tset a plane\n");
+       fprintf(stderr, "\t-P <connector_id>:<w>x<h>@<format>\tset a plane\n");
        fprintf(stderr, "\n\tDefault is to dump all info.\n");
        exit(0);
 }
 
 #define dump_resource(res) if (res) dump_##res()
 
-static int page_flipping_supported(int fd)
+static int page_flipping_supported(void)
 {
        /*FIXME: generic ioctl needed? */
        return 1;
@@ -769,12 +1134,13 @@ static int page_flipping_supported(int fd)
 int main(int argc, char **argv)
 {
        int c;
-       int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
+       int encoders = 0, connectors = 0, crtcs = 0, planes = 0, framebuffers = 0;
        int test_vsync = 0;
-       char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos-drm" };
-       char *modeset = NULL;
-       int i, count = 0;
+       char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos" };
+       unsigned int i;
+       int count = 0, plane_count = 0;
        struct connector con_args[2];
+       struct plane plane_args[2] = {0};
        
        opterr = 0;
        while ((c = getopt(argc, argv, optstr)) != -1) {
@@ -787,6 +1153,7 @@ int main(int argc, char **argv)
                        break;
                case 'p':
                        crtcs = 1;
+                       planes = 1;
                        break;
                case 'm':
                        modes = 1;
@@ -798,7 +1165,6 @@ int main(int argc, char **argv)
                        test_vsync = 1;
                        break;
                case 's':
-                       modeset = strdup(optarg);
                        con_args[count].crtc = -1;
                        if (sscanf(optarg, "%d:%64s",
                                   &con_args[count].id,
@@ -810,6 +1176,20 @@ int main(int argc, char **argv)
                                usage(argv[0]);
                        count++;                                      
                        break;
+               case 'P':
+                       strcpy(plane_args[plane_count].format_str, "XR24");
+                       if (sscanf(optarg, "%d:%dx%d@%4s",
+                                       &plane_args[plane_count].con_id,
+                                       &plane_args[plane_count].w,
+                                       &plane_args[plane_count].h,
+                                       plane_args[plane_count].format_str) != 4 &&
+                               sscanf(optarg, "%d:%dx%d",
+                                       &plane_args[plane_count].con_id,
+                                       &plane_args[plane_count].w,
+                                       &plane_args[plane_count].h) != 3)
+                               usage(argv[0]);
+                       plane_count++;
+                       break;
                default:
                        usage(argv[0]);
                        break;
@@ -817,7 +1197,7 @@ int main(int argc, char **argv)
        }
 
        if (argc == 1)
-               encoders = connectors = crtcs = modes = framebuffers = 1;
+               encoders = connectors = crtcs = planes = modes = framebuffers = 1;
 
        for (i = 0; i < ARRAY_SIZE(modules); i++) {
                printf("trying to load module %s...", modules[i]);
@@ -830,7 +1210,7 @@ int main(int argc, char **argv)
                }
        }
 
-       if (test_vsync && !page_flipping_supported(fd)) {
+       if (test_vsync && !page_flipping_supported()) {
                fprintf(stderr, "page flipping not supported by drm.\n");
                return -1;
        }
@@ -851,10 +1231,11 @@ int main(int argc, char **argv)
        dump_resource(encoders);
        dump_resource(connectors);
        dump_resource(crtcs);
+       dump_resource(planes);
        dump_resource(framebuffers);
 
        if (count > 0) {
-               set_mode(con_args, count, test_vsync);
+               set_mode(con_args, count, plane_args, plane_count, test_vsync);
                getchar();
        }
 
diff --git a/tests/planetest/planetest.c b/tests/planetest/planetest.c
deleted file mode 100644 (file)
index 3d05003..0000000
+++ /dev/null
@@ -1,468 +0,0 @@
-#include "config.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <string.h>
-#include <errno.h>
-#include <getopt.h>
-
-#include "xf86drm.h"
-#include "xf86drmMode.h"
-#include "libkms.h"
-#include "exynos_drm.h"
-
-#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
-
-drmModeRes *resources;
-int fd;
-
-struct connector {
-       uint32_t id;
-       char mode_str[64];
-       drmModeModeInfo *mode;
-       drmModeEncoder *encoder;
-       int crtc;
-       unsigned int fb_id[2], current_fb_id;
-       struct timeval start;
-
-       int swap_count;
-};
-
-struct fb_data {
-       struct kms_driver *kms;
-       struct kms_bo *bo;
-       unsigned int fb_id;
-};
-
-static void
-connector_find_mode(struct connector *c)
-{
-       drmModeConnector *connector;
-       int i, j;
-
-       /* First, find the connector & mode */
-       c->mode = NULL;
-       for (i = 0; i < resources->count_connectors; i++) {
-               connector = drmModeGetConnector(fd, resources->connectors[i]);
-
-               if (!connector) {
-                       fprintf(stderr, "could not get connector %i: %s\n",
-                               resources->connectors[i], strerror(errno));
-                       drmModeFreeConnector(connector);
-                       continue;
-               }
-
-               if (!connector->count_modes) {
-                       drmModeFreeConnector(connector);
-                       continue;
-               }
-
-               if (connector->connector_id != c->id) {
-                       drmModeFreeConnector(connector);
-                       continue;
-               }
-
-               for (j = 0; j < connector->count_modes; j++) {
-                       c->mode = &connector->modes[j];
-                       if (!strcmp(c->mode->name, c->mode_str))
-                               break;
-               }
-
-               /* Found it, break out */
-               if (c->mode)
-                       break;
-
-               drmModeFreeConnector(connector);
-       }
-
-       if (!c->mode) {
-               fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
-               return;
-       }
-
-       /* Now get the encoder */
-       for (i = 0; i < resources->count_encoders; i++) {
-               c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
-
-               if (!c->encoder) {
-                       fprintf(stderr, "could not get encoder %i: %s\n",
-                               resources->encoders[i], strerror(errno));
-                       drmModeFreeEncoder(c->encoder);
-                       continue;
-               }
-
-               if (c->encoder->encoder_id  == connector->encoder_id)
-                       break;
-
-               drmModeFreeEncoder(c->encoder);
-       }
-
-       if (c->crtc == -1)
-               c->crtc = c->encoder->crtc_id;
-}
-
-static struct kms_bo *
-allocate_buffer(struct kms_driver *kms,
-               int width, int height, unsigned *stride)
-{
-       struct kms_bo *bo;
-       unsigned bo_attribs[] = {
-               KMS_WIDTH,   0,
-               KMS_HEIGHT,  0,
-               KMS_BO_TYPE, KMS_BO_TYPE_SCANOUT_X8R8G8B8,
-               KMS_TERMINATE_PROP_LIST
-       };
-       int ret;
-
-       bo_attribs[1] = width;
-       bo_attribs[3] = height;
-
-       ret = kms_bo_create(kms, bo_attribs, &bo);
-       if (ret) {
-               fprintf(stderr, "failed to alloc buffer: %s\n",
-                       strerror(-ret));
-               return NULL;
-       }
-
-       ret = kms_bo_get_prop(bo, KMS_PITCH, stride);
-       if (ret) {
-               fprintf(stderr, "failed to retreive buffer stride: %s\n",
-                       strerror(-ret));
-               kms_bo_destroy(&bo);
-               return NULL;
-       }
-
-       return bo;
-}
-
-static int
-create_grey_buffer(struct kms_driver *kms,
-                  int width, int height, int *stride_out,
-                  struct kms_bo **bo_out, int color)
-{
-       struct kms_bo *bo;
-       int size, ret;
-       unsigned stride;
-       void *virtual;
-
-       bo = allocate_buffer(kms, width, height, &stride);
-       if (!bo)
-               return -1;
-
-       ret = kms_bo_map(bo, &virtual);
-       if (ret) {
-               fprintf(stderr, "failed to map buffer: %s\n",
-                       strerror(-ret));
-               kms_bo_destroy(&bo);
-               return -1;
-       }
-
-       size = stride * height;
-       memset(virtual, color, size);
-       kms_bo_unmap(bo);
-
-       *bo_out = bo;
-       *stride_out = stride;
-
-       return 0;
-}
-
-static int
-connector_find_plane(struct connector *c)
-{
-       drmModePlaneRes *plane_resources;
-       drmModePlane *ovr;
-       uint32_t id = 0;
-       int i;
-
-       plane_resources = drmModeGetPlaneResources(fd);
-       if (!plane_resources) {
-               fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
-                       strerror(errno));
-               return 0;
-       }
-
-       for (i = 0; i < plane_resources->count_planes; i++) {
-               ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
-               if (!ovr) {
-                       fprintf(stderr, "drmModeGetPlane failed: %s\n",
-                               strerror(errno));
-                       continue;
-               }
-
-               if (ovr->possible_crtcs & (1<<i)) {
-                       id = ovr->plane_id;
-                       drmModeFreePlane(ovr);
-                       break;
-               }
-               drmModeFreePlane(ovr);
-       }
-
-       return id;
-}
-
-static int
-connector_find_plane2(struct connector *c, unsigned int *plane_id)
-{
-       drmModePlaneRes *plane_resources;
-       drmModePlane *ovr;
-       int i;
-
-       plane_resources = drmModeGetPlaneResources(fd);
-       if (!plane_resources) {
-               fprintf(stderr, "drmModeGetPlaneResources failed: %s\n",
-                       strerror(errno));
-               return -1;
-       }
-
-       for (i = 0; i < plane_resources->count_planes; i++) {
-               plane_id[i] = 0;
-
-               ovr = drmModeGetPlane(fd, plane_resources->planes[i]);
-               if (!ovr) {
-                       fprintf(stderr, "drmModeGetPlane failed: %s\n",
-                               strerror(errno));
-                       continue;
-               }
-
-               if (ovr->possible_crtcs & (1 << 0))
-                       plane_id[i] = ovr->plane_id;
-               drmModeFreePlane(ovr);
-       }
-
-       return 0;
-}
-
-static struct fb_data *make_fb(int w, int h, int color)
-{
-       struct fb_data *fb_data;
-       struct kms_driver *kms;
-       struct kms_bo *bo;
-       unsigned int fb_id;
-       unsigned handle;
-       int stride;
-       int err;
-
-       fb_data = malloc(sizeof(struct fb_data));
-       if (!fb_data)
-               return NULL;
-
-       memset(fb_data, 0, sizeof(struct fb_data));
-
-       err = kms_create(fd, &kms);
-       if (err) {
-               fprintf(stderr, "failed to create kms driver: %s\n",
-                       strerror(-err));
-               goto err_alloc;
-       }
-
-       if (create_grey_buffer(kms, w, h, &stride, &bo, color))
-               goto err_alloc;
-
-       kms_bo_get_prop(bo, KMS_HANDLE, &handle);
-       err = drmModeAddFB(fd, w, h, 32, 32, stride, handle, &fb_id);
-       if (err) {
-               fprintf(stderr, "failed to add fb: %s\n", strerror(errno));
-               goto err_alloc;
-       }
-
-       fb_data->fb_id = fb_id;
-       fb_data->kms = kms;
-       fb_data->bo = bo;
-
-       return fb_data;
-
-err_alloc:
-       free(fb_data);
-       return NULL;
-}
-
-static int exynos_plane_set_zpos(int fd, unsigned int plane_id, int zpos)
-{
-       struct drm_exynos_plane_set_zpos zpos_req;
-       int ret;
-
-       zpos_req.plane_id = plane_id;
-       zpos_req.zpos = zpos;
-
-       ret = ioctl(fd, DRM_IOCTL_EXYNOS_PLANE_SET_ZPOS, &zpos_req);
-       if (ret < 0) {
-               fprintf(stderr, "failed to set plane zpos: %s\n",
-                               strerror(-ret));
-               return ret;
-       }
-
-       return 0;
-}
-
-#define PLANE_NR       5
-static void planetest_start(int nr, int start_plane, int crtc, int connector)
-{
-       struct connector c;
-       struct fb_data *fb_data[PLANE_NR];
-       unsigned int plane_id[PLANE_NR];
-       int height;
-       int width;
-       int x;
-       int y;
-       int i;
-       int ret;
-
-       c.id = connector;
-       c.crtc = crtc;
-
-       if (nr < 1 || nr > PLANE_NR) {
-               fprintf(stderr, "wrong plane count\n");
-               return;
-       }
-
-       if (start_plane < 0 || start_plane > (nr -1) ) {
-               fprintf(stderr, "Wrong start plane\n");
-               return;
-       }
-
-       connector_find_mode(&c);
-
-       if (c.mode == NULL) {
-               fprintf(stderr, "mode is NULL\n");
-               return;
-       }
-
-       width = c.mode->hdisplay;
-       height = c.mode->vdisplay;
-
-       width /= 8;
-       height /= 8;
-       x = width;
-       y = height;
-
-       ret = connector_find_plane2(&c, plane_id);
-       if (ret < 0)
-               goto err;
-
-       for (i = start_plane; i < nr; i++) {
-               if (!plane_id[i])
-                       continue;
-
-               fb_data[i] = make_fb(width, height, 0x30 + 0x20 * i);
-               if (!fb_data[i])
-                       return;
-
-               if (exynos_plane_set_zpos(fd, plane_id[i], i))
-                       goto err;
-
-               if (drmModeSetPlane(fd, plane_id[i], c.crtc, fb_data[i]->fb_id,
-                                       0, x, y, width, height,
-                                       0, 0, width, height)) {
-                       fprintf(stderr, "failed to enable plane: %s\n",
-                                       strerror(errno));
-                       goto err;
-               }
-
-               x += width - 30;
-               y += height - 30;
-               width += 40;
-               height += 40;
-       }
-
-       getchar();
-
-err:
-       for (i = start_plane; i < nr; i++) {
-               if (fb_data[i]) {
-                       kms_bo_destroy(&fb_data[i]->bo);
-                       kms_destroy(&fb_data[i]->kms);
-                       free(fb_data[i]);
-               }
-
-               if (!plane_id[i])
-                       continue;
-
-               if (drmModeSetPlane(fd, plane_id[i], c.crtc,
-                               0, 0, 0, 0, /* fb_id, flags, crtc_x, crtc_y */
-                               0, 0, /* crtc_w, crtc_h */
-                               0, 0, 0, 0 /* src_XXX */)) {
-                       fprintf(stderr, "failed to enable plane: %s\n",
-                                       strerror(errno));
-                       goto err;
-               }
-       }
-}
-
-static void help(void)
-{
-       printf("Usage: ./planetest [OPTION]\n"
-              " [OPTION]\n"
-              " -s <connector_id>@<crtc_id>/<plane count>/<start_plane>\n"
-              " -h Usage\n"
-              "\n"
-              "Default: connector 11, crtc 3, plane_count 5, start_plane 1\n");
-       exit(0);
-}
-
-static char optstr[] = "hs:";
-
-int main(int argc, char **argv)
-{
-       char *modules[] = { "exynos-drm" };
-       int opt;
-       int i, connector_id, nr, start_plane;
-       uint32_t crtc_id;
-
-       // default option (LCD)
-       crtc_id = 3;
-       connector_id = 11;
-       nr = 5;
-       start_plane = 1;
-
-       /* parse args */
-       opterr = 0;
-       while ((opt = getopt(argc, argv, optstr)) != -1) {
-               switch (opt) {
-               case 's':
-                       if (sscanf(optarg, "%d@%d/%d/%d",
-                                  &connector_id,
-                                  &crtc_id,
-                                  &nr,
-                                  &start_plane) != 4) {
-                               help();
-                               break;
-                       }
-                       break;
-               case 'h':
-               default:
-                       help();
-                       break;
-               }
-               break;
-       }
-
-       for (i = 0; i < ARRAY_SIZE(modules); i++) {
-               printf("trying to load module %s...", modules[i]);
-               fd = drmOpen(modules[i], NULL);
-               if (fd < 0) {
-                       printf("failed.\n");
-               } else {
-                       printf("success.\n");
-                       break;
-               }
-       }
-
-       resources = drmModeGetResources(fd);
-       if (!resources) {
-               fprintf(stderr, "drmModeGetResources failed: %s\n",
-                       strerror(errno));
-               drmClose(fd);
-               return 1;
-       }
-
-       planetest_start(nr, start_plane, crtc_id, connector_id);
-
-       /* TODO */
-
-       drmModeFreeResources(resources);
-
-       return 0;
-}
diff --git a/tests/proptest/Makefile.am b/tests/proptest/Makefile.am
new file mode 100644 (file)
index 0000000..f81a3c0
--- /dev/null
@@ -0,0 +1,11 @@
+AM_CFLAGS = \
+       -I$(top_srcdir)/include/drm \
+       -I$(top_srcdir)
+
+noinst_PROGRAMS = \
+       proptest
+
+proptest_SOURCES = \
+       proptest.c
+proptest_LDADD = \
+       $(top_builddir)/libdrm.la
diff --git a/tests/proptest/proptest.c b/tests/proptest/proptest.c
new file mode 100644 (file)
index 0000000..c6684eb
--- /dev/null
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2012 Intel Corporation
+ *
+ * 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:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ *
+ * Authors:
+ *    Paulo Zanoni <paulo.r.zanoni@intel.com>
+ *
+ */
+
+#include <assert.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+int fd;
+drmModeResPtr res = NULL;
+drmModePlaneResPtr plane_res = NULL;
+
+const char *connector_type_str(uint32_t type)
+{
+       switch (type) {
+       case DRM_MODE_CONNECTOR_Unknown:
+               return "Unknown";
+       case DRM_MODE_CONNECTOR_VGA:
+               return "VGA";
+       case DRM_MODE_CONNECTOR_DVII:
+               return "DVI-I";
+       case DRM_MODE_CONNECTOR_DVID:
+               return "DVI-D";
+       case DRM_MODE_CONNECTOR_DVIA:
+               return "DVI-A";
+       case DRM_MODE_CONNECTOR_Composite:
+               return "Composite";
+       case DRM_MODE_CONNECTOR_SVIDEO:
+               return "SVIDEO";
+       case DRM_MODE_CONNECTOR_LVDS:
+               return "LVDS";
+       case DRM_MODE_CONNECTOR_Component:
+               return "Component";
+       case DRM_MODE_CONNECTOR_9PinDIN:
+               return "9PinDin";
+       case DRM_MODE_CONNECTOR_DisplayPort:
+               return "DisplayPort";
+       case DRM_MODE_CONNECTOR_HDMIA:
+               return "HDMI-A";
+       case DRM_MODE_CONNECTOR_HDMIB:
+               return "HDMI-B";
+       case DRM_MODE_CONNECTOR_TV:
+               return "TV";
+       case DRM_MODE_CONNECTOR_eDP:
+               return "eDP";
+       default:
+               return "Invalid";
+       }
+}
+
+/* dump_blob and dump_prop shamelessly copied from ../modetest/modetest.c */
+static void
+dump_blob(uint32_t blob_id)
+{
+       uint32_t i;
+       unsigned char *blob_data;
+       drmModePropertyBlobPtr blob;
+
+       blob = drmModeGetPropertyBlob(fd, blob_id);
+       if (!blob)
+               return;
+
+       blob_data = blob->data;
+
+       for (i = 0; i < blob->length; i++) {
+               if (i % 16 == 0)
+                       printf("\n\t\t\t");
+               printf("%.2hhx", blob_data[i]);
+       }
+       printf("\n");
+
+       drmModeFreePropertyBlob(blob);
+}
+
+static void
+dump_prop(uint32_t prop_id, uint64_t value)
+{
+       int i;
+       drmModePropertyPtr prop;
+
+       prop = drmModeGetProperty(fd, prop_id);
+
+       printf("\t%d", prop_id);
+       if (!prop) {
+               printf("\n");
+               return;
+       }
+
+       printf(" %s:\n", prop->name);
+
+       printf("\t\tflags:");
+       if (prop->flags & DRM_MODE_PROP_PENDING)
+               printf(" pending");
+       if (prop->flags & DRM_MODE_PROP_RANGE)
+               printf(" range");
+       if (prop->flags & DRM_MODE_PROP_IMMUTABLE)
+               printf(" immutable");
+       if (prop->flags & DRM_MODE_PROP_ENUM)
+               printf(" enum");
+       if (prop->flags & DRM_MODE_PROP_BITMASK)
+               printf(" bitmask");
+       if (prop->flags & DRM_MODE_PROP_BLOB)
+               printf(" blob");
+       printf("\n");
+
+       if (prop->flags & DRM_MODE_PROP_RANGE) {
+               printf("\t\tvalues:");
+               for (i = 0; i < prop->count_values; i++)
+                       printf(" %"PRIu64, prop->values[i]);
+               printf("\n");
+       }
+
+       if (prop->flags & DRM_MODE_PROP_ENUM) {
+               printf("\t\tenums:");
+               for (i = 0; i < prop->count_enums; i++)
+                       printf(" %s=%llu", prop->enums[i].name,
+                              prop->enums[i].value);
+               printf("\n");
+       } else if (prop->flags & DRM_MODE_PROP_BITMASK) {
+               printf("\t\tvalues:");
+               for (i = 0; i < prop->count_enums; i++)
+                       printf(" %s=0x%llx", prop->enums[i].name,
+                              (1LL << prop->enums[i].value));
+               printf("\n");
+       } else {
+               assert(prop->count_enums == 0);
+       }
+
+       if (prop->flags & DRM_MODE_PROP_BLOB) {
+               printf("\t\tblobs:");
+               for (i = 0; i < prop->count_blobs; i++)
+                       dump_blob(prop->blob_ids[i]);
+               printf("\n");
+       } else {
+               assert(prop->count_blobs == 0);
+       }
+
+       printf("\t\tvalue:");
+       if (prop->flags & DRM_MODE_PROP_BLOB) {
+               dump_blob(value);
+               printf("\n");
+       } else {
+               printf(" %"PRIu64"\n", value);
+       }
+
+       drmModeFreeProperty(prop);
+}
+
+static void listObjectProperties(uint32_t id, uint32_t type)
+{
+       unsigned int i;
+       drmModeObjectPropertiesPtr props;
+
+       props = drmModeObjectGetProperties(fd, id, type);
+
+       if (!props) {
+               printf("\tNo properties: %s.\n", strerror(errno));
+               return;
+       }
+
+       for (i = 0; i < props->count_props; i++)
+               dump_prop(props->props[i], props->prop_values[i]);
+
+       drmModeFreeObjectProperties(props);
+}
+
+static void listConnectorProperties(void)
+{
+       int i;
+       drmModeConnectorPtr c;
+
+       for (i = 0; i < res->count_connectors; i++) {
+               c = drmModeGetConnector(fd, res->connectors[i]);
+
+               if (!c) {
+                       fprintf(stderr, "Could not get connector %u: %s\n",
+                               res->connectors[i], strerror(errno));
+                       continue;
+               }
+
+               printf("Connector %u (%s-%u)\n", c->connector_id,
+                      connector_type_str(c->connector_type),
+                      c->connector_type_id);
+
+               listObjectProperties(c->connector_id,
+                                    DRM_MODE_OBJECT_CONNECTOR);
+
+               drmModeFreeConnector(c);
+       }
+}
+
+static void listCrtcProperties(void)
+{
+       int i;
+       drmModeCrtcPtr c;
+
+       for (i = 0; i < res->count_crtcs; i++) {
+               c = drmModeGetCrtc(fd, res->crtcs[i]);
+
+               if (!c) {
+                       fprintf(stderr, "Could not get crtc %u: %s\n",
+                               res->crtcs[i], strerror(errno));
+                       continue;
+               }
+
+               printf("CRTC %u\n", c->crtc_id);
+
+               listObjectProperties(c->crtc_id, DRM_MODE_OBJECT_CRTC);
+
+               drmModeFreeCrtc(c);
+       }
+}
+
+static void listPlaneProperties(void)
+{
+       int i;
+       drmModePlanePtr p;
+
+       for (i = 0; i < plane_res->count_planes; i++) {
+               p = drmModeGetPlane(fd, plane_res->planes[i]);
+
+               if (!p) {
+                       fprintf(stderr, "Could not get plane %u: %s\n",
+                               plane_res->planes[i], strerror(errno));
+                       continue;
+               }
+
+               printf("Plane %u\n", p->plane_id);
+
+               listObjectProperties(p->plane_id, DRM_MODE_OBJECT_PLANE);
+
+               drmModeFreePlane(p);
+       }
+}
+
+static void listAllProperties(void)
+{
+       listConnectorProperties();
+       listCrtcProperties();
+       listPlaneProperties();
+}
+
+static int setProperty(char *argv[])
+{
+       uint32_t obj_id, obj_type, prop_id;
+       uint64_t value;
+
+       obj_id = atoi(argv[1]);
+
+       if (!strcmp(argv[2], "connector")) {
+               obj_type = DRM_MODE_OBJECT_CONNECTOR;
+       } else if (!strcmp(argv[2], "crtc")) {
+               obj_type = DRM_MODE_OBJECT_CRTC;
+       } else if (!strcmp(argv[2], "plane")) {
+               obj_type = DRM_MODE_OBJECT_PLANE;
+       } else {
+               fprintf(stderr, "Invalid object type.\n");
+               return 1;
+       }
+
+       prop_id = atoi(argv[3]);
+       value = atoll(argv[4]);
+
+       return drmModeObjectSetProperty(fd, obj_id, obj_type, prop_id, value);
+}
+
+static void printUsage(void)
+{
+       printf("Usage:\n"
+"  proptest\n"
+"  proptest [obj id] [obj type] [prop id] [value]\n"
+"\n"
+"The first form just prints all the existing properties. The second one is\n"
+"used to set the value of a specified property. The object type can be one of\n"
+"the following strings:\n"
+"  connector crtc plane\n"
+"\n"
+"Example:\n"
+"  proptest 7 connector 2 1\n"
+"will set property 2 of connector 7 to 1\n");
+}
+
+int main(int argc, char *argv[])
+{
+       char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "omapdrm", "exynos" };
+       unsigned int i, ret = 0;
+
+       for (i = 0; i < ARRAY_SIZE(modules); i++){
+               fd = drmOpen(modules[i], NULL);
+               if (fd >= 0) {
+                       printf("Module %s loaded.\n", modules[i]);
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(modules)) {
+               fprintf(stderr, "Failed to load drm modules.\n");
+               return 1;
+       }
+
+       res = drmModeGetResources(fd);
+       if (!res) {
+               fprintf(stderr, "Failed to get resources: %s\n",
+                       strerror(errno));
+               ret = 1;
+               goto done;
+       }
+
+       plane_res = drmModeGetPlaneResources(fd);
+       if (!plane_res) {
+               fprintf(stderr, "Failed to get plane resources: %s\n",
+                       strerror(errno));
+               ret = 1;
+               goto done;
+       }
+
+       if (argc < 2) {
+               listAllProperties();
+       } else if (argc == 5) {
+               ret = setProperty(argv);
+       } else {
+               printUsage();
+               ret = 1;
+       }
+
+       drmModeFreeResources(res);
+done:
+       drmClose(fd);
+       return ret;
+}
diff --git a/tests/rottest/Makefile.am b/tests/rottest/Makefile.am
new file mode 100644 (file)
index 0000000..966173f
--- /dev/null
@@ -0,0 +1,21 @@
+AM_CFLAGS = \
+       -I$(top_srcdir)/include/drm \
+       -I$(top_srcdir)/libkms/ \
+       -I$(top_srcdir)/exynos/ \
+       -I$(top_srcdir) \
+       $(CAIRO_CFLAGS)
+
+noinst_PROGRAMS = \
+       rottest
+
+rottest_SOURCES = \
+       rottest.c \
+       gem.c \
+       util.c \
+       rotator.c
+
+rottest_LDADD = \
+       $(top_builddir)/libdrm.la \
+       $(top_builddir)/libkms/libkms.la \
+       $(top_builddir)/exynos/libdrm_exynos.la \
+       $(CAIRO_LIBS)
diff --git a/tests/rottest/gem.c b/tests/rottest/gem.c
new file mode 100644 (file)
index 0000000..f5bf811
--- /dev/null
@@ -0,0 +1,92 @@
+/*
+ * DRM based rotator test program
+ * Copyright 2012 Samsung Electronics
+ *   YoungJun Cho <yj44.cho@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+#include "libkms.h"
+
+#include "exynos_drm.h"
+
+int exynos_gem_create(int fd, struct drm_exynos_gem_create *gem)
+{
+       int ret = 0;
+
+       if (!gem) {
+               fprintf(stderr, "gem object is null.\n");
+               return -EFAULT;
+       }
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CREATE, gem);
+       if (ret < 0)
+               fprintf(stderr, "failed to create gem buffer: %s\n",
+                                                               strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_userptr(int fd, struct drm_exynos_gem_userptr *gem_userptr)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_USERPTR, gem_userptr);
+       if (ret < 0)
+               fprintf(stderr, "failed to userptr: %s\n", strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_MMAP, in_mmap);
+       if (ret < 0)
+               fprintf(stderr, "failed to mmap: %s\n", strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_close(int fd, struct drm_gem_close *gem_close)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_GEM_CLOSE, gem_close);
+       if (ret < 0)
+               fprintf(stderr, "failed to close: %s\n", strerror(-ret));
+       return ret;
+}
+
+int exynos_gem_cache_op(int fd, struct drm_exynos_gem_cache_op *cache_op)
+{
+       int ret = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_GEM_CACHE_OP, cache_op);
+       if (ret < 0)
+               fprintf(stderr, "failed to cache op: %s\n", strerror(-ret));
+       return ret;
+}
diff --git a/tests/rottest/gem.h b/tests/rottest/gem.h
new file mode 100644 (file)
index 0000000..2a5ed1d
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __GEM_H__
+#define __GEM_H__
+
+extern int exynos_gem_create(int fd, struct drm_exynos_gem_create *gem);
+extern int exynos_gem_userptr(int fd,
+                               struct drm_exynos_gem_userptr *gem_userptr);
+extern int exynos_gem_mmap(int fd, struct drm_exynos_gem_mmap *in_mmap);
+extern int exynos_gem_close(int fd, struct drm_gem_close *gem_close);
+extern int exynos_gem_cache_op(int fd,
+                               struct drm_exynos_gem_cache_op *cache_op);
+
+#endif
diff --git a/tests/rottest/rotator.c b/tests/rottest/rotator.c
new file mode 100644 (file)
index 0000000..996385b
--- /dev/null
@@ -0,0 +1,297 @@
+/*
+ * DRM based rotator test program
+ * Copyright 2012 Samsung Electronics
+ *   YoungJun Cho <yj44.cho@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include "exynos_drm.h"
+#include "rottest.h"
+#include "gem.h"
+#include "util.h"
+
+#include "drm_fourcc.h"
+
+static int exynos_drm_ipp_property(int fd,
+                               struct drm_exynos_ipp_property *property,
+                               struct drm_exynos_pos *pos,
+                               struct drm_exynos_sz *sz)
+{
+       int ret = 0;
+
+       memset(property, 0x00, sizeof(struct drm_exynos_ipp_property));
+
+       property->config[EXYNOS_DRM_OPS_SRC].ops_id = EXYNOS_DRM_OPS_SRC;
+       property->config[EXYNOS_DRM_OPS_SRC].flip = EXYNOS_DRM_FLIP_NONE;
+       property->config[EXYNOS_DRM_OPS_SRC].degree = EXYNOS_DRM_DEGREE_0;
+       property->config[EXYNOS_DRM_OPS_SRC].fmt = DRM_FORMAT_XRGB8888;
+       property->config[EXYNOS_DRM_OPS_SRC].pos = *pos;
+       property->config[EXYNOS_DRM_OPS_SRC].sz = *sz;
+
+       property->config[EXYNOS_DRM_OPS_DST].ops_id = EXYNOS_DRM_OPS_DST;
+       property->config[EXYNOS_DRM_OPS_DST].flip = EXYNOS_DRM_FLIP_NONE;
+       property->config[EXYNOS_DRM_OPS_DST].degree = EXYNOS_DRM_DEGREE_90;
+       property->config[EXYNOS_DRM_OPS_DST].fmt = DRM_FORMAT_XRGB8888;
+       property->config[EXYNOS_DRM_OPS_DST].pos = *pos;
+       property->config[EXYNOS_DRM_OPS_DST].sz = *sz;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_IPP_PROPERTY, property);
+       if (ret)
+               fprintf(stderr,
+                       "failed to DRM_IOCTL_EXYNOS_IPP_PROPERTY : %s\n",
+                       strerror(errno));
+
+       return ret;
+}
+
+static int exynos_drm_ipp_buf(int fd, struct drm_exynos_ipp_buf *buf,
+                                       enum drm_exynos_ops_id ops_id,
+                                       enum drm_exynos_ipp_buf_ctrl ctrl,
+                                       unsigned int gem_handle)
+{
+       int ret = 0;
+
+       memset(buf, 0x00, sizeof(struct drm_exynos_ipp_buf));
+
+       buf->ops_id = ops_id;
+       buf->buf_ctrl = ctrl;
+       buf->user_data = 0;
+       buf->id = 0;
+       buf->handle[EXYNOS_DRM_PLANAR_Y] = gem_handle;
+       buf->handle[EXYNOS_DRM_PLANAR_CB] = 0;
+       buf->handle[EXYNOS_DRM_PLANAR_CR] = 0;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_IPP_BUF, buf);
+       if (ret)
+               fprintf(stderr,
+               "failed to DRM_IOCTL_EXYNOS_IPP_BUF[id:%d][ctrl:%d] : %s\n",
+               ops_id, ctrl, strerror(errno));
+       return ret;
+}
+
+static int exynos_drm_ipp_ctrl(int fd, struct drm_exynos_ipp_ctrl *ctrl,
+                               enum drm_exynos_ipp_cmd cmd, unsigned int use)
+{
+       int ret = 0;
+
+       memset(ctrl, 0x00, sizeof(struct drm_exynos_ipp_ctrl));
+
+       ctrl->cmd = cmd;
+       ctrl->use = use;
+
+       ret = ioctl(fd, DRM_IOCTL_EXYNOS_IPP_CTRL, ctrl);
+       if (ret)
+               fprintf(stderr,
+               "failed to DRM_IOCTL_EXYNOS_IPP_CTRL[cmd:%d][use:%d] : %s\n",
+               cmd, use, strerror(errno));
+
+       return ret;
+}
+
+void rotator_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec)
+{
+       struct drm_exynos_pos def_pos = {0, 0, 720, 1280};
+       struct drm_exynos_sz def_sz = {720, 1280};
+       struct drm_exynos_ipp_property property;
+       struct drm_exynos_ipp_buf buf1, buf2;
+       struct drm_exynos_ipp_ctrl ctrl;
+       unsigned int width, height, stride;
+       int ret, i, j, x;
+       struct drm_exynos_gem_create gem1, gem2;
+       struct drm_exynos_gem_mmap mmap1, mmap2;
+       void *usr_addr1, *usr_addr2;
+       struct timeval begin, end;
+       struct drm_gem_close args;
+       char filename[100];
+
+       /* For property */
+       ret = exynos_drm_ipp_property(fd, &property, &def_pos, &def_sz);
+       if (ret) {
+               fprintf(stderr, "failed to ipp property\n");
+               return;
+       }
+
+       /* For mode */
+       width = height = 0;
+       for (i = 0; i < count; i++) {
+               connector_find_mode(&c[i]);
+               if (c[i].mode == NULL) continue;
+               width += c[i].mode->hdisplay;
+               if (height < c[i].mode->vdisplay) height = c[i].mode->vdisplay;
+       }
+       stride = width * 4;
+
+       /* For source buffer */
+       ret = util_gem_create_mmap(fd, &gem1, &mmap1, stride * height);
+       if (ret) {
+               fprintf(stderr, "failed to gem create mmap: %s\n",
+                                                       strerror(errno));
+               if (ret == -1) return;
+               else if (ret == -2) goto err_gem_mmap1;
+       }
+       usr_addr1 = (void *)(unsigned long)mmap1.mapped;
+
+       util_draw_buffer(usr_addr1, 1, width, height, stride, 0);
+
+       sprintf(filename, "/opt/media/rot_src.bmp", j);
+       util_write_bmp(filename, usr_addr1, width, height);
+
+       /* For destination buffer */
+       ret = util_gem_create_mmap(fd, &gem2, &mmap2, stride * height);
+       if (ret) {
+               fprintf(stderr, "failed to gem create mmap: %s\n",
+                                                       strerror(errno));
+               if (ret == -1) goto err_gem_create2;
+               else if (ret == -2) goto err_gem_mmap2;
+       }
+       usr_addr2 = (void*)(unsigned long)mmap2.mapped;
+
+       util_draw_buffer(usr_addr2, 0, 0, 0, 0, mmap2.size);
+
+       sprintf(filename, "/opt/media/rot_dst.bmp", j);
+       util_write_bmp(filename, usr_addr2, height, width);
+
+       /* For source buffer map to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf1, EXYNOS_DRM_OPS_SRC,
+                                       IPP_BUF_CTRL_MAP, gem1.handle);
+       if (ret) {
+               fprintf(stderr, "failed to ipp buf src map\n");
+               goto err_ipp_buf_map1;
+       }
+
+       /* For destination buffer map to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST,
+                                       IPP_BUF_CTRL_MAP, gem2.handle);
+       if (ret) {
+               fprintf(stderr, "failed to ipp buf dst map\n");
+               goto err_ipp_buf_map2;
+       }
+
+       for (j = 0; j < MAX_LOOP; j++) {
+               /* Start */
+               gettimeofday(&begin, NULL);
+               ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_M2M, 1);
+               if (ret) {
+                       fprintf(stderr,
+                               "failed to ipp ctrl IPP_CMD_M2M start\n");
+                       goto err_ipp_ctrl_start;
+               }
+
+               while (1) {
+                       struct timeval timeout = { .tv_sec = 3, .tv_usec = 0 };
+                       fd_set fds;
+
+                       FD_ZERO(&fds);
+                       FD_SET(0, &fds);
+                       FD_SET(fd, &fds);
+                       ret = select(fd + 1, &fds, NULL, NULL, &timeout);
+                       if (ret <= 0) {
+                               fprintf(stderr, "select timed out or error.\n");
+                               continue;
+                       } else if (FD_ISSET(0, &fds)) {
+                               break;
+                       }
+
+                       gettimeofday(&end, NULL);
+                       usec[j] = (end.tv_sec - begin.tv_sec) * 1000000 +
+                                               (end.tv_usec - begin.tv_usec);
+
+                       sprintf(filename, "/opt/media/rot_%d.bmp", j);
+                       util_write_bmp(filename, usr_addr2, height, width);
+
+                       break;
+               }
+
+               /* For destination buffer queue to IPP */
+               ret = exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST,
+                                       IPP_BUF_CTRL_QUEUE, gem2.handle);
+               if (ret) {
+                       fprintf(stderr, "failed to ipp buf dst queue\n");
+                       goto err_ipp_ctrl_start;
+               }
+       }
+
+       /* For source buffer unmap to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf1, EXYNOS_DRM_OPS_SRC,
+                                       IPP_BUF_CTRL_UNMAP, gem1.handle);
+       if (ret) {
+               fprintf(stderr, "failed to ipp buf src unmap\n");
+               goto err_ipp_buf_unmap;
+       }
+
+       /* For destination buffer unmap to IPP */
+       ret = exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST,
+                                       IPP_BUF_CTRL_UNMAP, gem2.handle);
+       if (ret < 0) {
+               fprintf(stderr, "failed to ipp buf dst unmap\n");
+               goto err_ipp_buf_unmap;
+       }
+
+       /* Stop */
+       ret = exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_M2M, 0);
+       if (ret) {
+               fprintf(stderr, "failed to ipp ctrl IPP_CMD_M2M stop\n");
+               goto err_ipp_buf_unmap;
+       }
+
+       munmap(usr_addr2, mmap2.size);
+       munmap(usr_addr1, mmap1.size);
+
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem2.handle;
+       exynos_gem_close(fd, &args);
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem1.handle;
+       exynos_gem_close(fd, &args);
+
+       return;
+
+err_ipp_buf_unmap:
+       exynos_drm_ipp_ctrl(fd, &ctrl, IPP_CMD_M2M, 0);
+err_ipp_ctrl_start:
+       exynos_drm_ipp_buf(fd, &buf2, EXYNOS_DRM_OPS_DST, IPP_BUF_CTRL_UNMAP,
+                                                               gem2.handle);
+err_ipp_buf_map2:
+       exynos_drm_ipp_buf(fd, &buf1, EXYNOS_DRM_OPS_SRC, IPP_BUF_CTRL_UNMAP,
+                                                               gem1.handle);
+err_ipp_buf_map1:
+       munmap(usr_addr2, mmap2.size);
+err_gem_mmap2:
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem2.handle;
+       exynos_gem_close(fd, &args);
+err_gem_create2:
+       munmap(usr_addr1, mmap1.size);
+err_gem_mmap1:
+       memset(&args, 0x00, sizeof(struct drm_gem_close));
+       args.handle = gem1.handle;
+       exynos_gem_close(fd, &args);
+}
diff --git a/tests/rottest/rotator.h b/tests/rottest/rotator.h
new file mode 100644 (file)
index 0000000..8835ee3
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef __ROTATOR_H__
+#define __ROTATOR_H__
+
+extern void rotator_set_mode(struct connector *c, int count, int page_flip,
+                                                               long int *usec);
+
+#endif
diff --git a/tests/rottest/rottest.c b/tests/rottest/rottest.c
new file mode 100644 (file)
index 0000000..1da52f3
--- /dev/null
@@ -0,0 +1,460 @@
+/*
+ * DRM based rotator test program
+ * Copyright 2012 Samsung Electronics
+ *   YoungJun Cho <yj44.cho@sasmsung.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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+/*
+ * This fairly simple test program dumps output in a similar format to the
+ * "xrandr" tool everyone knows & loves.  It's necessarily slightly different
+ * since the kernel separates outputs into encoder and connector structures,
+ * each with their own unique ID.  The program also allows test testing of the
+ * memory management and mode setting APIs by allowing the user to specify a
+ * connector and mode to use for mode setting.  If all works as expected, a
+ * blue background should be painted on the monitor attached to the specified
+ * connector after the selected mode is set.
+ *
+ */
+
+#include "config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/poll.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+
+#include "libkms.h"
+
+#include "exynos_drm.h"
+
+#include "rottest.h"
+#include "rotator.h"
+
+drmModeRes *resources;
+int fd, modes;
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct type_name {
+       int type;
+       char *name;
+};
+
+#define type_name_fn(res) \
+char * res##_str(int type) {                   \
+       int i;                                          \
+       for (i = 0; i < ARRAY_SIZE(res##_names); i++) { \
+               if (res##_names[i].type == type)        \
+                       return res##_names[i].name;     \
+       }                                               \
+       return "(invalid)";                             \
+}
+
+struct type_name encoder_type_names[] = {
+       { DRM_MODE_ENCODER_NONE, "none" },
+       { DRM_MODE_ENCODER_DAC, "DAC" },
+       { DRM_MODE_ENCODER_TMDS, "TMDS" },
+       { DRM_MODE_ENCODER_LVDS, "LVDS" },
+       { DRM_MODE_ENCODER_TVDAC, "TVDAC" },
+};
+
+type_name_fn(encoder_type)
+
+struct type_name connector_status_names[] = {
+       { DRM_MODE_CONNECTED, "connected" },
+       { DRM_MODE_DISCONNECTED, "disconnected" },
+       { DRM_MODE_UNKNOWNCONNECTION, "unknown" },
+};
+
+type_name_fn(connector_status)
+
+struct type_name connector_type_names[] = {
+       { DRM_MODE_CONNECTOR_Unknown, "unknown" },
+       { DRM_MODE_CONNECTOR_VGA, "VGA" },
+       { DRM_MODE_CONNECTOR_DVII, "DVI-I" },
+       { DRM_MODE_CONNECTOR_DVID, "DVI-D" },
+       { DRM_MODE_CONNECTOR_DVIA, "DVI-A" },
+       { DRM_MODE_CONNECTOR_Composite, "composite" },
+       { DRM_MODE_CONNECTOR_SVIDEO, "s-video" },
+       { DRM_MODE_CONNECTOR_LVDS, "LVDS" },
+       { DRM_MODE_CONNECTOR_Component, "component" },
+       { DRM_MODE_CONNECTOR_9PinDIN, "9-pin DIN" },
+       { DRM_MODE_CONNECTOR_DisplayPort, "displayport" },
+       { DRM_MODE_CONNECTOR_HDMIA, "HDMI-A" },
+       { DRM_MODE_CONNECTOR_HDMIB, "HDMI-B" },
+       { DRM_MODE_CONNECTOR_TV, "TV" },
+       { DRM_MODE_CONNECTOR_eDP, "embedded displayport" },
+       { DRM_MODE_CONNECTOR_VIRTUAL, "Virtual" },
+};
+
+type_name_fn(connector_type)
+
+static void dump_encoders(void)
+{
+       drmModeEncoder *encoder;
+       int i;
+
+       printf("Encoders:\n");
+       printf("id\tcrtc\ttype\tpossible crtcs\tpossible clones\t\n");
+       for (i = 0; i < resources->count_encoders; i++) {
+               encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+               if (!encoder) {
+                       fprintf(stderr, "could not get encoder %i: %s\n",
+                               resources->encoders[i], strerror(errno));
+                       continue;
+               }
+               printf("%d\t%d\t%s\t0x%08x\t0x%08x\n",
+                      encoder->encoder_id,
+                      encoder->crtc_id,
+                      encoder_type_str(encoder->encoder_type),
+                      encoder->possible_crtcs,
+                      encoder->possible_clones);
+               drmModeFreeEncoder(encoder);
+       }
+       printf("\n");
+}
+
+static void dump_mode(drmModeModeInfo *mode)
+{
+       printf("  %s %d %d %d %d %d %d %d %d %d\n",
+              mode->name,
+              mode->vrefresh,
+              mode->hdisplay,
+              mode->hsync_start,
+              mode->hsync_end,
+              mode->htotal,
+              mode->vdisplay,
+              mode->vsync_start,
+              mode->vsync_end,
+              mode->vtotal);
+}
+
+static void dump_props(drmModeConnector *connector)
+{
+       drmModePropertyPtr props;
+       int i;
+
+       for (i = 0; i < connector->count_props; i++) {
+               props = drmModeGetProperty(fd, connector->props[i]);
+               printf("\t%s, flags %d\n", props->name, props->flags);
+               drmModeFreeProperty(props);
+       }
+}
+
+static void dump_connectors(void)
+{
+       drmModeConnector *connector;
+       int i, j;
+
+       printf("Connectors:\n");
+       printf("id\tencoder\tstatus\t\ttype\tsize (mm)\tmodes\tencoders\n");
+       for (i = 0; i < resources->count_connectors; i++) {
+               connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+               if (!connector) {
+                       fprintf(stderr, "could not get connector %i: %s\n",
+                               resources->connectors[i], strerror(errno));
+                       continue;
+               }
+
+               printf("%d\t%d\t%s\t%s\t%dx%d\t\t%d\t",
+                      connector->connector_id,
+                      connector->encoder_id,
+                      connector_status_str(connector->connection),
+                      connector_type_str(connector->connector_type),
+                      connector->mmWidth, connector->mmHeight,
+                      connector->count_modes);
+
+               for (j = 0; j < connector->count_encoders; j++)
+                       printf("%s%d", j > 0 ? ", " : "",
+                                                       connector->encoders[j]);
+               printf("\n");
+
+               if (!connector->count_modes)
+                       continue;
+
+               printf("  modes:\n");
+               printf("  name refresh (Hz) hdisp hss hse htot vdisp "
+                      "vss vse vtot)\n");
+               for (j = 0; j < connector->count_modes; j++)
+                       dump_mode(&connector->modes[j]);
+
+               printf("  props:\n");
+               dump_props(connector);
+
+               drmModeFreeConnector(connector);
+       }
+       printf("\n");
+}
+
+static void dump_crtcs(void)
+{
+       drmModeCrtc *crtc;
+       int i;
+
+       printf("CRTCs:\n");
+       printf("id\tfb\tpos\tsize\n");
+       for (i = 0; i < resources->count_crtcs; i++) {
+               crtc = drmModeGetCrtc(fd, resources->crtcs[i]);
+
+               if (!crtc) {
+                       fprintf(stderr, "could not get crtc %i: %s\n",
+                               resources->crtcs[i], strerror(errno));
+                       continue;
+               }
+               printf("%d\t%d\t(%d,%d)\t(%dx%d)\n",
+                      crtc->crtc_id,
+                      crtc->buffer_id,
+                      crtc->x, crtc->y,
+                      crtc->width, crtc->height);
+               dump_mode(&crtc->mode);
+
+               drmModeFreeCrtc(crtc);
+       }
+       printf("\n");
+}
+
+static void dump_framebuffers(void)
+{
+       drmModeFB *fb;
+       int i;
+
+       printf("Frame buffers:\n");
+       printf("id\tsize\tpitch\n");
+       for (i = 0; i < resources->count_fbs; i++) {
+               fb = drmModeGetFB(fd, resources->fbs[i]);
+
+               if (!fb) {
+                       fprintf(stderr, "could not get fb %i: %s\n",
+                               resources->fbs[i], strerror(errno));
+                       continue;
+               }
+               printf("%u\t(%ux%u)\t%u\n",
+                      fb->fb_id,
+                      fb->width, fb->height,
+                      fb->pitch);
+
+               drmModeFreeFB(fb);
+       }
+       printf("\n");
+}
+
+/*
+ * Mode setting with the kernel interfaces is a bit of a chore.
+ * First you have to find the connector in question and make sure the
+ * requested mode is available.
+ * Then you need to find the encoder attached to that connector so you
+ * can bind it with a free crtc.
+ */
+
+void connector_find_mode(struct connector *c)
+{
+       drmModeConnector *connector;
+       int i, j;
+
+       /* First, find the connector & mode */
+       c->mode = NULL;
+       for (i = 0; i < resources->count_connectors; i++) {
+               connector = drmModeGetConnector(fd, resources->connectors[i]);
+
+               if (!connector) {
+                       fprintf(stderr, "could not get connector %i: %s\n",
+                               resources->connectors[i], strerror(errno));
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (!connector->count_modes) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               if (connector->connector_id != c->id) {
+                       drmModeFreeConnector(connector);
+                       continue;
+               }
+
+               for (j = 0; j < connector->count_modes; j++) {
+                       c->mode = &connector->modes[j];
+                       if (!strcmp(c->mode->name, c->mode_str))
+                               break;
+               }
+
+               /* Found it, break out */
+               if (c->mode)
+                       break;
+
+               drmModeFreeConnector(connector);
+       }
+
+       if (!c->mode) {
+               fprintf(stderr, "failed to find mode \"%s\"\n", c->mode_str);
+               return;
+       }
+
+       /* Now get the encoder */
+       for (i = 0; i < resources->count_encoders; i++) {
+               c->encoder = drmModeGetEncoder(fd, resources->encoders[i]);
+
+               if (!c->encoder) {
+                       fprintf(stderr, "could not get encoder %i: %s\n",
+                               resources->encoders[i], strerror(errno));
+                       drmModeFreeEncoder(c->encoder);
+                       continue;
+               }
+
+               if (c->encoder->encoder_id  == connector->encoder_id)
+                       break;
+
+               drmModeFreeEncoder(c->encoder);
+       }
+
+       if (c->crtc == -1)
+               c->crtc = c->encoder->crtc_id;
+}
+
+extern char *optarg;
+extern int optind, opterr, optopt;
+static char optstr[] = "ecpmfs:v";
+
+static void usage(char *name)
+{
+       fprintf(stderr, "usage: %s [-ecpmf]\n", name);
+       fprintf(stderr, "\t-e\tlist encoders\n");
+       fprintf(stderr, "\t-c\tlist connectors\n");
+       fprintf(stderr, "\t-p\tlist CRTCs (pipes)\n");
+       fprintf(stderr, "\t-m\tlist modes\n");
+       fprintf(stderr, "\t-f\tlist framebuffers\n");
+       fprintf(stderr, "\t-v\ttest vsynced page flipping\n");
+       fprintf(stderr, "\t-s <connector_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\t-s <connector_id>@<crtc_id>:<mode>\tset a mode\n");
+       fprintf(stderr, "\n\tDefault is to dump all info.\n");
+       exit(0);
+}
+
+#define dump_resource(res) if (res) dump_##res()
+
+int main(int argc, char **argv)
+{
+       int c;
+       int encoders = 0, connectors = 0, crtcs = 0, framebuffers = 0;
+       int test_vsync = 0;
+       char *modules[] = {"exynos", "i915", "radeon", "nouveau", "vmwgfx"};
+       char *modeset = NULL;
+       int i, count = 0;
+       struct connector con_args[2];
+       
+       opterr = 0;
+       while ((c = getopt(argc, argv, optstr)) != -1) {
+               switch (c) {
+               case 'e':
+                       encoders = 1;
+                       break;
+               case 'c':
+                       connectors = 1;
+                       break;
+               case 'p':
+                       crtcs = 1;
+                       break;
+               case 'm':
+                       modes = 1;
+                       break;
+               case 'f':
+                       framebuffers = 1;
+                       break;
+               case 'v':
+                       test_vsync = 1;
+                       break;
+               case 's':
+                       modeset = strdup(optarg);
+                       con_args[count].crtc = -1;
+                       if (sscanf(optarg, "%d:%64s",
+                                  &con_args[count].id,
+                                  con_args[count].mode_str) != 2 &&
+                           sscanf(optarg, "%d@%d:%64s",
+                                  &con_args[count].id,
+                                  &con_args[count].crtc,
+                                  con_args[count].mode_str) != 3)
+                               usage(argv[0]);
+                       count++;
+                       break;
+               default:
+                       usage(argv[0]);
+                       break;
+               }
+       }
+
+       if (argc == 1)
+               encoders = connectors = crtcs = modes = framebuffers = 1;
+
+       for (i = 0; i < ARRAY_SIZE(modules); i++) {
+               printf("trying to load module %s...", modules[i]);
+               fd = drmOpen(modules[i], NULL);
+               if (fd < 0) {
+                       printf("failed.\n");
+               } else {
+                       printf("success.\n");
+                       break;
+               }
+       }
+
+       if (i == ARRAY_SIZE(modules)) {
+               fprintf(stderr, "failed to load any modules, aborting.\n");
+               return -1;
+       }
+
+       resources = drmModeGetResources(fd);
+       if (!resources) {
+               fprintf(stderr, "drmModeGetResources failed: %s\n",
+                       strerror(errno));
+               drmClose(fd);
+               return 1;
+       }
+
+       dump_resource(encoders);
+       dump_resource(connectors);
+       dump_resource(crtcs);
+       dump_resource(framebuffers);
+
+       if (count > 0) {
+               long int sum = 0, usec[MAX_LOOP];
+
+               rotator_set_mode(con_args, count, test_vsync, usec);
+               for (i = 0; i < MAX_LOOP; i++) {
+                       printf("[%d] : %d\n", i + 1, usec[i]);
+                       sum += usec[i];
+               }
+               printf("rotator : cma\n");
+               printf("avg : [%d]\n", sum / MAX_LOOP);
+               getchar();
+       }
+
+       drmModeFreeResources(resources);
+
+       return 0;
+}
diff --git a/tests/rottest/rottest.h b/tests/rottest/rottest.h
new file mode 100644 (file)
index 0000000..0edb3ca
--- /dev/null
@@ -0,0 +1,25 @@
+#ifndef __ROTTEST_H__
+#define __ROTTEST_H__
+
+#include "xf86drm.h"
+#include "xf86drmMode.h"
+
+#define MAX_LOOP 20
+
+struct connector {
+       uint32_t id;
+       char mode_str[64];
+       drmModeModeInfo *mode;
+       drmModeEncoder *encoder;
+       int crtc;
+       unsigned int fb_id[2], current_fb_id;
+       struct timeval start;
+
+       int swap_count;
+};
+
+extern int fd;
+
+extern void connector_find_mode(struct connector *c);
+
+#endif
diff --git a/tests/rottest/util.c b/tests/rottest/util.c
new file mode 100644 (file)
index 0000000..8800c48
--- /dev/null
@@ -0,0 +1,132 @@
+/*
+ * DRM based rotator test program
+ * Copyright 2012 Samsung Electronics
+ *   YoungJun Cho <yj44.cho@samsung.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 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:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND 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.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+
+#include "exynos_drm.h"
+#include "gem.h"
+
+int util_gem_create_mmap(int fd, struct drm_exynos_gem_create *gem,
+                                       struct drm_exynos_gem_mmap *mmap,
+                                       unsigned int size)
+{
+       /* initialize structure for gem create */
+       memset(gem, 0x00, sizeof(struct drm_exynos_gem_create));
+       gem->size = size;
+
+       if (exynos_gem_create(fd, gem) < 0) {
+               fprintf(stderr, "failed to gem create: %s\n", strerror(errno));
+               return -1;
+       }
+
+       /* initialize structure for gem mmap */
+       memset(mmap, 0x00, sizeof(struct drm_exynos_gem_mmap));
+       mmap->handle = gem->handle;
+       mmap->size = gem->size;
+
+       if (exynos_gem_mmap(fd, mmap) < 0) {
+               fprintf(stderr, "failed to gem mmap: %s\n", strerror(errno));
+               return -2;
+       }
+
+       return 0;
+}
+
+void util_draw_buffer(void *addr, unsigned int stripe,
+                               unsigned int width, unsigned int height,
+                               unsigned int stride, unsigned int size)
+{
+       if (stripe == 1) {
+               int i, j;
+               unsigned int *fb_ptr;
+               div_t d;
+
+               for (j = 0; j < height; j++) {
+                       fb_ptr = (unsigned int *)((char *)addr + j * stride);
+                       for (i = 0; i < width; i++) {
+                               d = div(i, width);
+                               fb_ptr[i] = 0x00130502 * (d.quot >> 6)
+                                               + 0x000a1120 * (d.rem >> 6);
+                       }
+               }
+       } else
+               memset(addr, 0x77, size);
+}
+
+int util_write_bmp(const char *file, const void *data, unsigned int width,
+                                                       unsigned int height)
+{
+       int i;
+       unsigned int * blocks;
+       FILE *fp;
+       struct {
+               unsigned char magic[2];
+       } bmpfile_magic = { {'B', 'M'} };
+       struct {
+               unsigned int filesz;
+               unsigned short creator1;
+               unsigned short creator2;
+               unsigned int bmp_offset;
+       } bmpfile_header = { 0, 0, 0, 0x36 };
+       struct {
+               unsigned int header_sz;
+               unsigned int width;
+               unsigned int height;
+               unsigned short nplanes;
+               unsigned short bitspp;
+               unsigned int compress_type;
+               unsigned int bmp_bytesz;
+               unsigned int hres;
+               unsigned int vres;
+               unsigned int ncolors;
+               unsigned int nimpcolors;
+       } bmp_dib_v3_header_t = { 0x28, 0, 0, 1, 32, 0, 0, 0, 0, 0, 0 };
+
+       fp = fopen(file, "wb");
+       if (fp == NULL) return -1;
+
+       bmpfile_header.filesz = sizeof(bmpfile_magic) + sizeof(bmpfile_header)
+                       + sizeof(bmp_dib_v3_header_t) + width * height * 4;
+       bmp_dib_v3_header_t.header_sz = sizeof(bmp_dib_v3_header_t);
+       bmp_dib_v3_header_t.width = width;
+       bmp_dib_v3_header_t.height = -height;
+       bmp_dib_v3_header_t.nplanes = 1;
+       bmp_dib_v3_header_t.bmp_bytesz = width * height * 4;
+
+       fwrite(&bmpfile_magic, sizeof(bmpfile_magic), 1, fp);
+       fwrite(&bmpfile_header, sizeof(bmpfile_header), 1, fp);
+       fwrite(&bmp_dib_v3_header_t, sizeof(bmp_dib_v3_header_t), 1, fp);
+
+       blocks = (unsigned int*)data;
+       for (i = 0; i < height * width; i++)
+               fwrite(&blocks[i], 4, 1, fp);
+
+       fclose(fp);
+       return 0;
+}
diff --git a/tests/rottest/util.h b/tests/rottest/util.h
new file mode 100644 (file)
index 0000000..e1ffcca
--- /dev/null
@@ -0,0 +1,12 @@
+#ifndef __UTIL_H__
+#define __UTIL_H__
+
+extern int util_gem_create_mmap(int fd, struct drm_exynos_gem_create *gem,
+                                       struct drm_exynos_gem_mmap *mmap,
+                                       unsigned int size);
+extern void util_draw_buffer(void *addr, unsigned int stripe,
+                               unsigned int width, unsigned int height,
+                               unsigned int stride, unsigned int size);
+extern int util_write_bmp(const char *file, const void *data,
+                               unsigned int width, unsigned int height);
+#endif
old mode 100755 (executable)
new mode 100644 (file)
index 20dae78..4fccd59 100644 (file)
@@ -103,7 +103,7 @@ static void usage(char *name)
 int main(int argc, char **argv)
 {
        int i, c, fd, ret;
-       char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos-drm" };
+       char *modules[] = { "i915", "radeon", "nouveau", "vmwgfx", "exynos" };
        drmVBlank vbl;
        drmEventContext evctx;
        struct vbl_info handler_info;
index 66cabc9..04fdf1f 100644 (file)
@@ -271,19 +271,14 @@ int drmModeAddFB2(int fd, uint32_t width, uint32_t height,
        f.height = height;
        f.pixel_format = pixel_format;
        f.flags = flags;
-       memcpy(f.handles, bo_handles, sizeof(uint32_t) * 4);
-       memcpy(f.pitches, pitches, sizeof(uint32_t) * 4);
-       memcpy(f.offsets, offsets, sizeof(uint32_t) * 4);
+       memcpy(f.handles, bo_handles, 4 * sizeof(bo_handles[0]));
+       memcpy(f.pitches, pitches, 4 * sizeof(pitches[0]));
+       memcpy(f.offsets, offsets, 4 * sizeof(offsets[0]));
 
        if ((ret = DRM_IOCTL(fd, DRM_IOCTL_MODE_ADDFB2, &f)))
                return ret;
 
        *buf_id = f.fb_id;
-
-       memcpy(bo_handles, f.handles, sizeof(uint32_t) * 4);
-       memcpy(pitches, f.pitches, sizeof(uint32_t) * 4);
-       memcpy(offsets, f.offsets, sizeof(uint32_t) * 4);
-
        return 0;
 }
 
@@ -580,7 +575,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)) {
@@ -602,7 +597,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) {
@@ -907,6 +902,7 @@ retry:
                                 ovr.count_format_types, sizeof(uint32_t));
        if (ovr.count_format_types && !r->formats) {
                drmFree(r->formats);
+               drmFree(r);
                r = 0;
        }
 
@@ -916,15 +912,6 @@ err_allocs:
        return r;
 }
 
-void drmModeFreePlaneResources(drmModePlaneResPtr ptr)
-{
-       if (!ptr)
-               return;
-
-       drmFree(ptr->planes);
-       drmFree(ptr);
-}
-
 void drmModeFreePlane(drmModePlanePtr ptr)
 {
        if (!ptr)
@@ -969,6 +956,7 @@ retry:
                                  res.count_planes, sizeof(uint32_t));
        if (res.count_planes && !r->planes) {
                drmFree(r->planes);
+               drmFree(r);
                r = 0;
        }
 
@@ -977,3 +965,95 @@ err_allocs:
 
        return r;
 }
+
+void drmModeFreePlaneResources(drmModePlaneResPtr ptr)
+{
+       if (!ptr)
+               return;
+
+       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);
+}
index 004e34c..4f49362 100644 (file)
@@ -33,6 +33,9 @@
  *
  */
 
+#ifndef _XF86DRMMODE_H_
+#define _XF86DRMMODE_H_
+
 #if defined(__cplusplus) || defined(c_plusplus)
 extern "C" {
 #endif
@@ -110,11 +113,12 @@ extern "C" {
 #define DRM_MODE_DITHERING_OFF  0
 #define DRM_MODE_DITHERING_ON   1
 
-#define DRM_MODE_ENCODER_NONE   0
-#define DRM_MODE_ENCODER_DAC    1
-#define DRM_MODE_ENCODER_TMDS   2
-#define DRM_MODE_ENCODER_LVDS   3
-#define DRM_MODE_ENCODER_TVDAC  4
+#define DRM_MODE_ENCODER_NONE          0
+#define DRM_MODE_ENCODER_DAC           1
+#define DRM_MODE_ENCODER_TMDS          2
+#define DRM_MODE_ENCODER_LVDS          3
+#define DRM_MODE_ENCODER_TVDAC         4
+#define DRM_MODE_ENCODER_VIRTUAL       5
 
 #define DRM_MODE_SUBCONNECTOR_Automatic 0
 #define DRM_MODE_SUBCONNECTOR_Unknown   0
@@ -139,6 +143,7 @@ extern "C" {
 #define DRM_MODE_CONNECTOR_HDMIB        12
 #define DRM_MODE_CONNECTOR_TV          13
 #define DRM_MODE_CONNECTOR_eDP         14
+#define DRM_MODE_CONNECTOR_VIRTUAL     15
 
 #define DRM_MODE_PROP_PENDING   (1<<0)
 #define DRM_MODE_PROP_RANGE     (1<<1)
@@ -278,6 +283,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;
@@ -304,8 +315,8 @@ extern void drmModeFreeFB( drmModeFBPtr ptr );
 extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
 extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
 extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
-extern void drmModeFreePlaneResources( drmModePlaneResPtr ptr );
 extern void drmModeFreePlane( drmModePlanePtr ptr );
+extern void drmModeFreePlaneResources(drmModePlaneResPtr ptr);
 
 /**
  * Retrives all of the resources associated with a card.
@@ -425,6 +436,16 @@ 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
+
+#endif