[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

xserver-xorg-video-intel: Changes to 'debian-experimental'



 configure.ac                       |   83 +-
 debian/changelog                   |    3 
 src/backlight.c                    |    2 
 src/compat-api.h                   |   23 
 src/i915_pciids.h                  |   32 -
 src/intel_device.c                 |   20 
 src/intel_driver.h                 |    1 
 src/intel_module.c                 |   11 
 src/intel_options.c                |   86 ++
 src/intel_options.h                |    2 
 src/legacy/i810/i810_memory.c      |    6 
 src/sna/blt.c                      |  361 ++++++++++++
 src/sna/compiler.h                 |    2 
 src/sna/gen2_render.c              |    6 
 src/sna/gen3_render.c              |   12 
 src/sna/gen4_render.c              |    8 
 src/sna/gen5_render.c              |    6 
 src/sna/gen6_common.h              |  110 +--
 src/sna/gen6_render.c              |   22 
 src/sna/gen7_render.c              |   37 -
 src/sna/gen8_render.c              |   34 -
 src/sna/kgem.c                     |  138 +++-
 src/sna/kgem.h                     |   26 
 src/sna/sna.h                      |   57 +
 src/sna/sna_accel.c                |  239 +++++---
 src/sna/sna_blt.c                  |   71 +-
 src/sna/sna_composite.c            |  104 ++-
 src/sna/sna_display.c              | 1103 ++++++++++++++++++++++++++++---------
 src/sna/sna_display_fake.c         |    3 
 src/sna/sna_dri2.c                 |  706 +++++++++++++----------
 src/sna/sna_driver.c               |  233 +++----
 src/sna/sna_glyphs.c               |    2 
 src/sna/sna_present.c              |  383 ++++++++++--
 src/sna/sna_render.c               |    4 
 src/sna/sna_render_inline.h        |    6 
 src/sna/sna_trapezoids_imprecise.c |  340 ++++-------
 src/sna/sna_trapezoids_mono.c      |   73 +-
 src/sna/sna_trapezoids_precise.c   |  340 ++++-------
 src/sna/sna_video.c                |   66 ++
 src/sna/sna_video.h                |    3 
 src/sna/sna_video_overlay.c        |   12 
 src/sna/sna_video_sprite.c         |    9 
 src/sna/sna_video_textured.c       |    5 
 src/sna/xassert.h                  |   11 
 src/uxa/i965_video.c               |    1 
 src/uxa/intel.h                    |   16 
 src/uxa/intel_display.c            |  115 +--
 src/uxa/intel_dri.c                |  484 +++++++++-------
 src/uxa/intel_driver.c             |   23 
 src/uxa/intel_present.c            |   24 
 test/dri2-race.c                   |  274 ++++++++-
 test/dri2-test.c                   |   30 -
 test/present-test.c                | 1065 ++++++++++++++++++++++++++++++++++-
 tools/.gitignore                   |    4 
 tools/Makefile.am                  |   15 
 tools/cursor.c                     |  108 +++
 tools/dri3info.c                   |  139 ++++
 tools/virtual.c                    |   18 
 58 files changed, 5233 insertions(+), 1884 deletions(-)

New commits:
commit fc50dfa7938f9550352da3bf321bfa1bd56e4240
Author: Timo Aaltonen <tjaalton@debian.org>
Date:   Fri Mar 20 10:59:03 2015 +0200

    bump the version

diff --git a/debian/changelog b/debian/changelog
index 7f101bd..2643758 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,6 @@
-xserver-xorg-video-intel (2:2.99.917-1~exp2) UNRELEASED; urgency=medium
+xserver-xorg-video-intel (2:2.99.917+git20150320-1~exp1) UNRELEASED; urgency=medium
 
+  * New snapshot.
   * rules: Fix valgrind-enabling check.
   * README.source: Mention that dpkg-source complains about symlinks
     which are real files on the tarball, and add a command to clean

commit 7fe2b2948652443ff43d907855bd7a051d54d309
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Mar 19 23:14:17 2015 +0000

    sna: Protect against ABI breakage in recent versions of libdrm
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 11f0828..6f16cba 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -182,6 +182,15 @@ struct local_i915_gem_caching {
 #define LOCAL_IOCTL_I915_GEM_SET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_SET_CACHING, struct local_i915_gem_caching)
 #define LOCAL_IOCTL_I915_GEM_GET_CACHING DRM_IOW(DRM_COMMAND_BASE + LOCAL_I915_GEM_GET_CACHING, struct local_i915_gem_caching)
 
+struct local_i915_gem_mmap {
+	uint32_t handle;
+	uint32_t pad;
+	uint64_t offset;
+	uint64_t size;
+	uint64_t addr_ptr;
+};
+#define LOCAL_IOCTL_I915_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MMAP, struct local_i915_gem_mmap)
+
 struct local_i915_gem_mmap2 {
 	uint32_t handle;
 	uint32_t pad;
@@ -514,15 +523,15 @@ retry_wc:
 
 static void *__kgem_bo_map__cpu(struct kgem *kgem, struct kgem_bo *bo)
 {
-	struct drm_i915_gem_mmap mmap_arg;
+	struct local_i915_gem_mmap arg;
 	int err;
 
 retry:
-	VG_CLEAR(mmap_arg);
-	mmap_arg.handle = bo->handle;
-	mmap_arg.offset = 0;
-	mmap_arg.size = bytes(bo);
-	if ((err = do_ioctl(kgem->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg))) {
+	VG_CLEAR(arg);
+	arg.handle = bo->handle;
+	arg.offset = 0;
+	arg.size = bytes(bo);
+	if ((err = do_ioctl(kgem->fd, LOCAL_IOCTL_I915_GEM_MMAP, &arg))) {
 		assert(err != EINVAL);
 
 		if (__kgem_throttle_retire(kgem, 0))
@@ -536,10 +545,10 @@ retry:
 		return NULL;
 	}
 
-	VG(VALGRIND_MAKE_MEM_DEFINED(mmap_arg.addr_ptr, bytes(bo)));
+	VG(VALGRIND_MAKE_MEM_DEFINED(arg.addr_ptr, bytes(bo)));
 
 	DBG(("%s: caching CPU vma for %d\n", __FUNCTION__, bo->handle));
-	return bo->map__cpu = (void *)(uintptr_t)mmap_arg.addr_ptr;
+	return bo->map__cpu = (void *)(uintptr_t)arg.addr_ptr;
 }
 
 static int gem_write(int fd, uint32_t handle,

commit bacaf7f18c2f4d3b5cb6bd6145dfb79fa4096759
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Tue Mar 17 09:45:09 2015 +0000

    sna: Use struct pixman_f_vector for compatibility with older pixman
    
    Or else face compile failures:
    
    blt.c: In function 'affine_blt':
    blt.c:1403:3: error: unknown type name 'pixman_f_vector_t'
    blt.c:1407:4: error: request for member 'v' in something not a structure or union
    blt.c:1408:4: error: request for member 'v' in something not a structure or union
    blt.c:1409:4: error: request for member 'v' in something not a structure or union
    blt.c:1411:3: warning: passing argument 2 of 'pixman_f_transform_point_3d' from incompatible pointer type [enabled by default]
    In file included from /usr/include/xorg/miscstruct.h:52:0,
                     from /usr/include/xorg/regionstr.h:52,
                     from /usr/include/xorg/region.h:50,
                     from /usr/include/xorg/window.h:51,
                     from /usr/include/xorg/input.h:55,
                     from /usr/include/xorg/xf86str.h:38,
                     from sna.h:43,
                     from blt.c:32:
    /usr/include/pixman-1/pixman.h:247:15: note: expected 'struct pixman_f_vector *' but argument is of type 'int *'
    blt.c:1413:7: error: request for member 'v' in something not a structure or union
    blt.c:1415:7: error: request for member 'v' in something not a structure or union
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/configure.ac b/configure.ac
index 28a4749..9aadc73 100644
--- a/configure.ac
+++ b/configure.ac
@@ -447,6 +447,7 @@ fi
 PKG_CHECK_MODULES(XORG, [xorg-server >= $required_xorg_server_version xproto fontsproto pixman-1 >= $required_pixman_version $REQUIRED_MODULES])
 ABI_VERSION=`$PKG_CONFIG --variable=abi_videodrv xorg-server`
 XSERVER_VERSION=`$PKG_CONFIG --modversion xorg-server`
+PIXMAN_VERSION=`$PKG_CONFIG --modversion pixman-1`
 
 if test "x$ONLY_UMS" = "xyes"; then
 	UMS="yes"
@@ -914,6 +915,7 @@ fi
 echo ""
 echo "AC_PACKAGE_STRING will be compiled with:"
 echo "  Xorg Video ABI version: $ABI_VERSION (xorg-server-$XSERVER_VERSION)"
+echo "  pixman version: pixman-1-$PIXMAN_VERSION"
 echo "  Acceleration backends:$accel_msg"
 echo "  Additional debugging support?$debug_msg"
 echo "  Support for Kernel Mode Setting? $KMS"
diff --git a/src/sna/blt.c b/src/sna/blt.c
index c534f75..9df7b2b 100644
--- a/src/sna/blt.c
+++ b/src/sna/blt.c
@@ -30,6 +30,7 @@
 #endif
 
 #include "sna.h"
+#include <pixman.h>
 
 #if __x86_64__
 #define USE_SSE2 1
@@ -1400,7 +1401,7 @@ affine_blt(const void *src, void *dst, int bpp,
 
 	for (j = 0; j < dst_height; j++) {
 		pixman_fixed_t x, y;
-		pixman_f_vector_t v;
+		struct pixman_f_vector v;
 		uint32_t *b;
 
 		/* reference point is the center of the pixel */

commit 9d0d78230aaf8863a96d75e8b57bb62e51121b8a
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 23:07:59 2015 +0000

    sna: Skip inplace operation to a busy clear GPU bo
    
    Since clearing is a relatively trivial operation, allow us to do the
    clear to a CPU bo rather than block on the GPU.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 2713dde..eda4c33 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -527,10 +527,10 @@ sna_pixmap_alloc_cpu(struct sna *sna,
 		DBG(("%s: allocating CPU buffer (%dx%d)\n", __FUNCTION__,
 		     pixmap->drawable.width, pixmap->drawable.height));
 
-		hint = 0;
-		if ((flags & MOVE_ASYNC_HINT) == 0 &&
-		    ((flags & MOVE_READ) == 0 || (priv->gpu_damage && !priv->clear && !sna->kgem.has_llc)))
-			hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE;
+		hint = CREATE_CPU_MAP | CREATE_INACTIVE | CREATE_NO_THROTTLE;
+		if ((flags & MOVE_ASYNC_HINT) ||
+		    (priv->gpu_damage && !priv->clear && kgem_bo_is_busy(priv->gpu_bo) && sna->kgem.can_blt_cpu))
+			hint = 0;
 
 		priv->cpu_bo = kgem_create_cpu_2d(&sna->kgem,
 						  pixmap->drawable.width,
@@ -1582,6 +1582,16 @@ static inline bool pixmap_inplace(struct sna *sna,
 		return false;
 
 	if (priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo)) {
+		if (priv->clear) {
+			DBG(("%s: no, clear GPU bo is busy\n", __FUNCTION__));
+			return false;
+		}
+
+		if (flags & MOVE_ASYNC_HINT) {
+			DBG(("%s: no, async hint and GPU bo is busy\n", __FUNCTION__));
+			return false;
+		}
+
 		if ((flags & (MOVE_WRITE | MOVE_READ)) == (MOVE_WRITE | MOVE_READ)) {
 			DBG(("%s: no, GPU bo is busy\n", __FUNCTION__));
 			return false;
@@ -2274,6 +2284,7 @@ skip_inplace_map:
 	    (flags & MOVE_WRITE ? (void *)priv->gpu_bo : (void *)priv->gpu_damage) && priv->cpu_damage == NULL &&
 	    priv->gpu_bo->tiling == I915_TILING_NONE &&
 	    (flags & MOVE_READ || kgem_bo_can_map__cpu(&sna->kgem, priv->gpu_bo, flags & MOVE_WRITE)) &&
+	    (!priv->clear || !kgem_bo_is_busy(priv->gpu_bo)) &&
 	    ((flags & (MOVE_WRITE | MOVE_ASYNC_HINT)) == 0 ||
 	     (!priv->cow && !priv->move_to_gpu && !__kgem_bo_is_busy(&sna->kgem, priv->gpu_bo)))) {
 		void *ptr;
@@ -2337,6 +2348,7 @@ skip_inplace_map:
 			     pixmap->devKind, pixmap->devKind * pixmap->drawable.height));
 
 			if (priv->cpu_bo) {
+				kgem_bo_undo(&sna->kgem, priv->cpu_bo);
 				if ((flags & MOVE_ASYNC_HINT || priv->cpu_bo->exec) &&
 				    sna->kgem.can_blt_cpu &&
 				    sna->render.fill_one(sna,

commit d8dd2b88a1f2bca63a2a6f42af035fd9fb1f685f
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 22:27:31 2015 +0000

    sna/gen6+: Demote BLT ring switching priority if semaphores are disabled
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/gen6_common.h b/src/sna/gen6_common.h
index bfdd66f..409bab3 100644
--- a/src/sna/gen6_common.h
+++ b/src/sna/gen6_common.h
@@ -106,12 +106,15 @@ static int prefer_blt_bo(struct sna *sna,
 
 inline static bool force_blt_ring(struct sna *sna)
 {
-	if (sna->flags & SNA_POWERSAVE)
-		return true;
-
 	if (sna->kgem.mode == KGEM_RENDER)
 		return false;
 
+	if (NO_RING_SWITCH(sna))
+		return sna->kgem.ring == KGEM_BLT;
+
+	if (sna->flags & SNA_POWERSAVE)
+		return true;
+
 	if (sna->render_state.gt < 2)
 		return true;
 

commit 66cb6c23d110300fff0235fd07408362e8491339
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 15:44:44 2015 +0000

    sna: Start demoting some assertions
    
    A few assertions are there to catch less desirable behaviour rather than
    outright errors. For these, just grab the backtrace and continue.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d75822f..11f0828 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -6261,8 +6261,8 @@ static void *__kgem_bo_map__gtt_or_wc(struct kgem *kgem, struct kgem_bo *bo)
 	kgem_trim_vma_cache(kgem, MAP_GTT, bucket(bo));
 
 	if (bo->tiling || !kgem->has_wc_mmap) {
-		assert(num_pages(bo) <= kgem->aperture_mappable / 2);
 		assert(kgem->gen != 021 || bo->tiling != I915_TILING_Y);
+		warn_unless(num_pages(bo) <= kgem->aperture_mappable / 2);
 
 		ptr = bo->map__gtt;
 		if (ptr == NULL)
diff --git a/src/sna/xassert.h b/src/sna/xassert.h
index 1bcfd08..bac70b8 100644
--- a/src/sna/xassert.h
+++ b/src/sna/xassert.h
@@ -43,6 +43,17 @@
 	xorg_backtrace(); \
 	FatalError("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \
 } while (0)
+
+#define warn_unless(E) do if (unlikely(!(E))) { \
+	static int __warn_once__; \
+	if (!__warn_once__) { \
+		xorg_backtrace(); \
+		ErrorF("%s:%d assertion '%s' failed\n", __func__, __LINE__, #E); \
+		__warn_once__ = 1; \
+	} \
+} while (0)
+#else
+#define warn_unless(E)
 #endif
 
 #endif /* __XASSERT_H__ */

commit 7863efebf5bee0dbdad55e5402e02413e26f7a4f
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 15:21:47 2015 +0000

    sna/gen6+: Relax assertions in light of !semaphores
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/gen6_common.h b/src/sna/gen6_common.h
index b619714..bfdd66f 100644
--- a/src/sna/gen6_common.h
+++ b/src/sna/gen6_common.h
@@ -125,7 +125,7 @@ prefer_blt_ring(struct sna *sna, struct kgem_bo *bo, unsigned flags)
 		return PREFER_RENDER < 0;
 
 	assert(!force_blt_ring(sna));
-	assert(!kgem_bo_is_render(bo));
+	assert(!kgem_bo_is_render(bo) || NO_RING_SWITCH(sna));
 
 	if (kgem_bo_is_blt(bo))
 		return true;

commit 359f12312ece78333162eb8fd191968a4b0030b6
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 15:21:26 2015 +0000

    sna: Fix assertions for transformed cursors
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 2ddbf6d..663853f 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -4854,8 +4854,8 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
 	       cursor ? cursor->serial : 0,
 	       sna->cursor.serial));
 	if (cursor && cursor->serial == sna->cursor.serial) {
-		assert(cursor->size == sna->cursor.size);
-		assert(cursor->rotation == crtc->transform_in_use ? crtc->rotation : RR_Rotate_0);
+		assert(cursor->size == sna->cursor.size || cursor->transformed);
+		assert(cursor->rotation == (!to_sna_crtc(crtc)->cursor_transform && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0);
 		assert(cursor->ref);
 		return cursor;
 	}
@@ -4868,7 +4868,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
 	       get_cursor_argb(sna->cursor.ref) != NULL));
 
 	transformed = to_sna_crtc(crtc)->cursor_transform;
-	rotation = !transformed && crtc->transform_in_use ? crtc->rotation : RR_Rotate_0;
+	rotation = (!transformed && crtc->transform_in_use) ? crtc->rotation : RR_Rotate_0;
 
 	/* Don't allow phys cursor sharing */
 	if (sna->cursor.use_gtt && !transformed) {

commit c2381ac065e0d7fc39ae029045eda54b36766324
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 14:39:56 2015 +0000

    sna: Remove redundant RRGetInfo on hotplug discovery
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index fae91d7..2ddbf6d 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -4460,8 +4460,11 @@ void sna_mode_discover(struct sna *sna)
 			continue;
 
 		sna_output->last_detect = 0;
-		if (sna_output->serial == serial)
+		if (sna_output->serial == serial) {
+			if (sna_output_detect(output) != output->status)
+				RROutputChanged(output->randr_output, TRUE);
 			continue;
+		}
 
 		DBG(("%s: removing output %s (id=%d), serial=%u [now %u]\n",
 		     __FUNCTION__, output->name, sna_output->id,
@@ -4496,6 +4499,8 @@ void sna_mode_discover(struct sna *sna)
 
 		xf86RandR12TellChanged(screen);
 	}
+
+	RRTellChanged(screen);
 }
 
 static void copy_front(struct sna *sna, PixmapPtr old, PixmapPtr new)
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index ab9ce04..5092bfb 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -770,7 +770,6 @@ sna_handle_uevents(int fd, void *closure)
 		if (scrn->vtSema) {
 			sna_mode_discover(sna);
 			sna_mode_check(sna);
-			RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
 		} else
 			sna->flags |= SNA_REPROBE;
 	}
@@ -1206,12 +1205,11 @@ static Bool sna_enter_vt(VT_FUNC_ARGS_DECL)
 		return FALSE;
 
 	if (sna->flags & SNA_REPROBE) {
-		DBG(("%s: reporting deferred hotplug event\n",
-		     __FUNCTION__));
+		DBG(("%s: reporting deferred hotplug event\n", __FUNCTION__));
 		sna_mode_discover(sna);
-		RRGetInfo(xf86ScrnToScreen(scrn), TRUE);
 		sna->flags &= ~SNA_REPROBE;
 	}
+	sna_mode_check(sna);
 
 	if (!sna_set_desired_mode(sna)) {
 		intel_put_master(sna->dev);

commit 2f1fb20d89b032f56737530ade3a22564e08cf4d
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 13:14:27 2015 +0000

    sna: Explicitly compute whether the transform is affine for HW cursors
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 0352a71..fae91d7 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -143,6 +143,7 @@ struct sna_crtc {
 	bool fallback_shadow;
 	bool transform;
 	bool cursor_transform;
+	bool hwcursor;
 	bool flip_pending;
 	uint8_t id;
 	uint8_t pipe;
@@ -1598,6 +1599,7 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
 	}
 
 	sna_crtc->cursor_transform = false;
+	sna_crtc->hwcursor = true;
 	assert(!sna_crtc->shadow);
 }
 
@@ -2211,6 +2213,14 @@ out_shadow:
 }
 
 #define SCALING_EPSILON (1./256)
+
+static bool
+is_affine(const struct pixman_f_transform *t)
+{
+	return (fabs(t->m[2][0]) < SCALING_EPSILON &&
+		fabs(t->m[2][1]) < SCALING_EPSILON);
+}
+
 static double determinant(const struct pixman_f_transform *t)
 {
 	return t->m[0][0]*t->m[1][1] - t->m[1][0]*t->m[0][1];
@@ -2219,12 +2229,7 @@ static double determinant(const struct pixman_f_transform *t)
 static bool
 affine_is_pixel_exact(const struct pixman_f_transform *t)
 {
-	double det;
-
-	if (t->m[2][0] || t->m[2][1])
-		return false;
-
-	det = t->m[2][2] * determinant(t);
+	double det = t->m[2][2] * determinant(t);
 	if (fabs (det * det - 1.0) < SCALING_EPSILON) {
 		if (fabs(t->m[0][1]) < SCALING_EPSILON &&
 		    fabs(t->m[1][0]) < SCALING_EPSILON)
@@ -2283,9 +2288,15 @@ static void sna_crtc_randr(xf86CrtcPtr crtc)
 	} else
 		crtc->transform_in_use = sna_crtc->rotation != RR_Rotate_0;
 
-	sna_crtc->cursor_transform = false;
-	if (crtc->transform_in_use)
-		sna_crtc->cursor_transform = !affine_is_pixel_exact(&f_fb_to_crtc);
+	if (needs_transform) {
+		sna_crtc->hwcursor = is_affine(&f_fb_to_crtc);
+		sna_crtc->cursor_transform =
+			sna_crtc->hwcursor &&
+			!affine_is_pixel_exact(&f_fb_to_crtc);
+	} else {
+		sna_crtc->hwcursor = true;
+		sna_crtc->cursor_transform = false;
+	}
 
 	crtc->crtc_to_framebuffer = crtc_to_fb;
 	crtc->f_crtc_to_framebuffer = f_crtc_to_fb;
@@ -2409,6 +2420,7 @@ __sna_crtc_set_mode(xf86CrtcPtr crtc)
 	struct kgem_bo *saved_bo, *bo;
 	uint32_t saved_offset;
 	bool saved_transform;
+	bool saved_hwcursor;
 	bool saved_cursor_transform;
 
 	DBG(("%s: CRTC=%d, pipe=%d, hidden?=%d\n", __FUNCTION__,
@@ -2419,6 +2431,7 @@ __sna_crtc_set_mode(xf86CrtcPtr crtc)
 	saved_bo = sna_crtc->bo;
 	saved_transform = sna_crtc->transform;
 	saved_cursor_transform = sna_crtc->cursor_transform;
+	saved_hwcursor = sna_crtc->hwcursor;
 	saved_offset = sna_crtc->offset;
 
 	sna_crtc->fallback_shadow = false;
@@ -2465,8 +2478,8 @@ retry: /* Attach per-crtc pixmap or direct */
 	if (sna_crtc->transform)
 		sna_crtc_damage(crtc);
 	if (sna_crtc->cursor &&  /* Reload cursor if RandR maybe changed */
-	    (saved_cursor_transform ||
-	     sna_crtc->cursor_transform ||
+	    (!sna_crtc->hwcursor ||
+	     saved_cursor_transform || sna_crtc->cursor_transform ||
 	     sna_crtc->cursor->rotation != crtc->rotation))
 		sna_crtc_disable_cursor(sna, sna_crtc);
 
@@ -2488,6 +2501,7 @@ error:
 		sna->mode.rr_active++;
 	sna_crtc->transform = saved_transform;
 	sna_crtc->cursor_transform = saved_cursor_transform;
+	sna_crtc->hwcursor = saved_hwcursor;
 	sna_crtc->bo = saved_bo;
 	sna_mode_discover(sna);
 	return FALSE;
@@ -5358,10 +5372,7 @@ transformable_cursor(struct sna *sna, CursorPtr cursor)
 		struct pixman_box16 box;
 		int size;
 
-		if (!crtc->transform_in_use)
-			continue;
-
-		if (!to_sna_crtc(crtc)->cursor_transform)
+		if (!to_sna_crtc(crtc)->hwcursor)
 			return false;
 
 		t = &crtc->f_crtc_to_framebuffer;

commit bc84ba6f97b2cdd5d9f2d0c4b5c7b6532ed5d0e6
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 12:12:21 2015 +0000

    sna: Fix computation of transformed cursor size
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 71988cd..0352a71 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -4872,7 +4872,7 @@ static struct sna_cursor *__sna_get_cursor(struct sna *sna, xf86CrtcPtr crtc)
 		box.x2 = sna->cursor.ref->bits->width;
 		box.y2 = sna->cursor.ref->bits->height;
 
-		pixman_f_transform_bounds(&crtc->f_framebuffer_to_crtc, &box);
+		pixman_f_transform_bounds(&crtc->f_crtc_to_framebuffer, &box);
 		size = __cursor_size(box.x2 - box.x1, box.y2 - box.y1);
 
 		RRTransformCompute(0, 0,
@@ -5364,7 +5364,7 @@ transformable_cursor(struct sna *sna, CursorPtr cursor)
 		if (!to_sna_crtc(crtc)->cursor_transform)
 			return false;
 
-		t = &crtc->f_framebuffer_to_crtc;
+		t = &crtc->f_crtc_to_framebuffer;
 		if (!sna->cursor.use_gtt || !sna->cursor.scratch)
 			return false;
 

commit 557ffa3bacd8e673fe8d4f141a74b037eb9de095
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Fri Mar 13 12:08:04 2015 +0000

    sna: Cross check that we only have an affine transformation for HW cursors
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index a71edb1..71988cd 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -5353,15 +5353,18 @@ transformable_cursor(struct sna *sna, CursorPtr cursor)
 	int i;
 
 	for (i = 0; i < sna->mode.num_real_crtc; i++) {
-		struct sna_crtc *crtc = to_sna_crtc(config->crtc[i]);
+		xf86CrtcPtr crtc = config->crtc[i];
 		const struct pixman_f_transform *t;
 		struct pixman_box16 box;
 		int size;
 
-		if (!crtc->cursor_transform)
+		if (!crtc->transform_in_use)
 			continue;
 
-		t = &crtc->base->f_framebuffer_to_crtc;
+		if (!to_sna_crtc(crtc)->cursor_transform)
+			return false;
+
+		t = &crtc->f_framebuffer_to_crtc;
 		if (!sna->cursor.use_gtt || !sna->cursor.scratch)
 			return false;
 

commit d867d48bb63273e72d45baaaf53cb23f0e493de5
Author: Chris Wilson <chris@chris-wilson.co.uk>
Date:   Thu Mar 12 22:29:29 2015 +0000

    sna: Apply affine transformations to HW cursors
    
    Until now we only applied pixel-exact rotations to the cursors. However,
    this left the cursors ignoring scaling and so appearing incorrect on
    outputs with transformations applied. An extra complications comes from
    making sure that the scaling routine is signal safe.
    
    Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>

diff --git a/src/sna/blt.c b/src/sna/blt.c
index dc4e3e1..c534f75 100644
--- a/src/sna/blt.c
+++ b/src/sna/blt.c
@@ -1240,3 +1240,241 @@ memcpy_xor(const void *src, void *dst, int bpp,
 		}
 	}
 }
+
+#define BILINEAR_INTERPOLATION_BITS 4
+static force_inline int
+bilinear_weight(pixman_fixed_t x)
+{
+	return (x >> (16 - BILINEAR_INTERPOLATION_BITS)) &
+		((1 << BILINEAR_INTERPOLATION_BITS) - 1);
+}
+
+#if BILINEAR_INTERPOLATION_BITS <= 4
+/* Inspired by Filter_32_opaque from Skia */
+static force_inline uint32_t
+bilinear_interpolation(uint32_t tl, uint32_t tr,
+		       uint32_t bl, uint32_t br,
+		       int distx, int disty)
+{
+	int distxy, distxiy, distixy, distixiy;
+	uint32_t lo, hi;
+
+	distx <<= (4 - BILINEAR_INTERPOLATION_BITS);
+	disty <<= (4 - BILINEAR_INTERPOLATION_BITS);
+
+	distxy = distx * disty;
+	distxiy = (distx << 4) - distxy;	/* distx * (16 - disty) */
+	distixy = (disty << 4) - distxy;	/* disty * (16 - distx) */
+	distixiy =
+		16 * 16 - (disty << 4) -
+		(distx << 4) + distxy; /* (16 - distx) * (16 - disty) */
+
+	lo = (tl & 0xff00ff) * distixiy;
+	hi = ((tl >> 8) & 0xff00ff) * distixiy;
+
+	lo += (tr & 0xff00ff) * distxiy;
+	hi += ((tr >> 8) & 0xff00ff) * distxiy;
+
+	lo += (bl & 0xff00ff) * distixy;
+	hi += ((bl >> 8) & 0xff00ff) * distixy;
+
+	lo += (br & 0xff00ff) * distxy;
+	hi += ((br >> 8) & 0xff00ff) * distxy;
+
+	return ((lo >> 8) & 0xff00ff) | (hi & ~0xff00ff);
+}
+#elif SIZEOF_LONG > 4
+static force_inline uint32_t
+bilinear_interpolation(uint32_t tl, uint32_t tr,
+		       uint32_t bl, uint32_t br,
+		       int distx, int disty)
+{
+	uint64_t distxy, distxiy, distixy, distixiy;
+	uint64_t tl64, tr64, bl64, br64;
+	uint64_t f, r;
+
+	distx <<= (8 - BILINEAR_INTERPOLATION_BITS);
+	disty <<= (8 - BILINEAR_INTERPOLATION_BITS);
+
+	distxy = distx * disty;
+	distxiy = distx * (256 - disty);
+	distixy = (256 - distx) * disty;
+	distixiy = (256 - distx) * (256 - disty);
+
+	/* Alpha and Blue */
+	tl64 = tl & 0xff0000ff;
+	tr64 = tr & 0xff0000ff;
+	bl64 = bl & 0xff0000ff;
+	br64 = br & 0xff0000ff;
+
+	f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
+	r = f & 0x0000ff0000ff0000ull;
+
+	/* Red and Green */
+	tl64 = tl;
+	tl64 = ((tl64 << 16) & 0x000000ff00000000ull) | (tl64 & 0x0000ff00ull);
+
+	tr64 = tr;
+	tr64 = ((tr64 << 16) & 0x000000ff00000000ull) | (tr64 & 0x0000ff00ull);
+
+	bl64 = bl;
+	bl64 = ((bl64 << 16) & 0x000000ff00000000ull) | (bl64 & 0x0000ff00ull);
+
+	br64 = br;
+	br64 = ((br64 << 16) & 0x000000ff00000000ull) | (br64 & 0x0000ff00ull);
+
+	f = tl64 * distixiy + tr64 * distxiy + bl64 * distixy + br64 * distxy;
+	r |= ((f >> 16) & 0x000000ff00000000ull) | (f & 0xff000000ull);
+
+	return (uint32_t)(r >> 16);
+}
+#else
+static force_inline uint32_t
+bilinear_interpolation(uint32_t tl, uint32_t tr,
+		       uint32_t bl, uint32_t br,
+		       int distx, int disty)
+{
+	int distxy, distxiy, distixy, distixiy;
+	uint32_t f, r;
+
+	distx <<= (8 - BILINEAR_INTERPOLATION_BITS);
+	disty <<= (8 - BILINEAR_INTERPOLATION_BITS);
+
+	distxy = distx * disty;
+	distxiy = (distx << 8) - distxy;	/* distx * (256 - disty) */
+	distixy = (disty << 8) - distxy;	/* disty * (256 - distx) */
+	distixiy =
+		256 * 256 - (disty << 8) -
+		(distx << 8) + distxy;		/* (256 - distx) * (256 - disty) */
+
+	/* Blue */
+	r = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy +
+	     (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy);
+
+	/* Green */
+	f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy +
+	     (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy);
+	r |= f & 0xff000000;
+
+	tl >>= 16;
+	tr >>= 16;
+	bl >>= 16;
+	br >>= 16;
+	r >>= 16;
+
+	/* Red */
+	f = ((tl & 0x000000ff) * distixiy + (tr & 0x000000ff) * distxiy +
+	     (bl & 0x000000ff) * distixy  + (br & 0x000000ff) * distxy);
+	r |= f & 0x00ff0000;
+
+	/* Alpha */
+	f = ((tl & 0x0000ff00) * distixiy + (tr & 0x0000ff00) * distxiy +
+	     (bl & 0x0000ff00) * distixy  + (br & 0x0000ff00) * distxy);
+	r |= f & 0xff000000;
+
+	return r;
+}
+#endif
+
+static inline uint32_t convert_pixel(const uint8_t *p, int x)
+{
+	return ((uint32_t *)p)[x];
+}
+
+fast void
+affine_blt(const void *src, void *dst, int bpp,
+	   int16_t src_x, int16_t src_y,
+	   int16_t src_width, int16_t src_height,
+	   int32_t src_stride,
+	   int16_t dst_x, int16_t dst_y,
+	   uint16_t dst_width, uint16_t dst_height,
+	   int32_t dst_stride,
+	   const struct pixman_f_transform *t)
+{
+	static const uint8_t zero[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
+	const pixman_fixed_t ux = pixman_double_to_fixed(t->m[0][0]);
+	const pixman_fixed_t uy = pixman_double_to_fixed(t->m[1][0]);
+	int i, j;
+
+	assert(bpp == 32);
+
+	for (j = 0; j < dst_height; j++) {
+		pixman_fixed_t x, y;
+		pixman_f_vector_t v;
+		uint32_t *b;
+
+		/* reference point is the center of the pixel */
+		v.v[0] = dst_x + 0.5;
+		v.v[1] = dst_y + j + 0.5;
+		v.v[2] = 1.0;
+
+		pixman_f_transform_point_3d(t, &v);
+
+		x = pixman_double_to_fixed(v.v[0]);
+		x += pixman_int_to_fixed(src_x - dst_x);
+		y = pixman_double_to_fixed(v.v[1]);
+		y +=  pixman_int_to_fixed(src_y - dst_y);
+
+		b = (uint32_t*)((uint8_t *)dst + (dst_y + j) * dst_stride + dst_x * bpp / 8);
+		for (i = 0; i < dst_width; i++) {
+			const uint8_t *row1;
+			const uint8_t *row2;
+			int x1, y1, x2, y2;
+			uint32_t tl, tr, bl, br;
+			int32_t fx, fy;
+
+			x1 = x - pixman_fixed_1/2;
+			y1 = y - pixman_fixed_1/2;
+
+			fx = bilinear_weight(x1);
+			fy = bilinear_weight(y1);
+
+			x1 = pixman_fixed_to_int(x1);
+			x2 = x1 + 1;
+			y1 = pixman_fixed_to_int(y1);
+			y2 = y1 + 1;
+
+			if (x1 >= src_width  || x2 < 0 ||
+			    y1 >= src_height || y2 < 0) {
+				b[i] = 0;
+				goto next;
+			}
+
+			if (y2 == 0) {
+				row1 = zero;
+			} else {
+				row1 = (uint8_t *)src + src_stride * y1;
+				row1 += bpp / 8 * x1;
+			}
+
+			if (y1 == src_height - 1) {
+				row2 = zero;
+			} else {
+				row2 = (uint8_t *)src + src_stride * y2;
+				row2 += bpp / 8 * x1;
+			}
+
+			if (x2 == 0) {
+				tl = 0;
+				bl = 0;
+			} else {
+				tl = convert_pixel(row1, 0);
+				bl = convert_pixel(row2, 0);
+			}
+
+			if (x1 == src_width - 1) {
+				tr = 0;
+				br = 0;
+			} else {
+				tr = convert_pixel(row1, 1);
+				br = convert_pixel(row2, 1);
+			}
+
+			b[i] = bilinear_interpolation(tl, tr, bl, br, fx, fy);
+
+next:
+			x += ux;
+			y += uy;
+		}
+	}
+}
diff --git a/src/sna/sna.h b/src/sna/sna.h
index 4018404..a498484 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -1141,6 +1141,16 @@ memcpy_blt(const void *src, void *dst, int bpp,
 	   uint16_t width, uint16_t height);
 
 void
+affine_blt(const void *src, void *dst, int bpp,
+	   int16_t src_x, int16_t src_y,
+	   int16_t src_width, int16_t src_height,
+	   int32_t src_stride,
+	   int16_t dst_x, int16_t dst_y,
+	   uint16_t dst_width, uint16_t dst_height,
+	   int32_t dst_stride,
+	   const struct pixman_f_transform *t);
+
+void
 memmove_box(const void *src, void *dst,
 	    int bpp, int32_t stride,
 	    const BoxRec *box,
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index a836b61..a71edb1 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -116,6 +116,20 @@ struct local_mode_obj_get_properties {
 
 extern XF86ConfigPtr xf86configptr;
 
+struct sna_cursor {
+	struct sna_cursor *next;
+	uint32_t *image;
+	bool transformed;
+	Rotation rotation;
+	int ref;
+	int size;
+	int last_width;
+	int last_height;
+	unsigned handle;
+	unsigned serial;
+	unsigned alloc;
+};
+
 struct sna_crtc {
 	xf86CrtcPtr base;
 	struct drm_mode_modeinfo kmode;
@@ -128,6 +142,7 @@ struct sna_crtc {
 	bool shadow;
 	bool fallback_shadow;
 	bool transform;
+	bool cursor_transform;
 	bool flip_pending;
 	uint8_t id;
 	uint8_t pipe;
@@ -1582,6 +1597,7 @@ __sna_crtc_disable(struct sna *sna, struct sna_crtc *sna_crtc)
 		sna_crtc->transform = false;
 	}
 
+	sna_crtc->cursor_transform = false;
 	assert(!sna_crtc->shadow);
 }
 
@@ -2194,6 +2210,34 @@ out_shadow:
 	}
 }
 
+#define SCALING_EPSILON (1./256)
+static double determinant(const struct pixman_f_transform *t)
+{
+	return t->m[0][0]*t->m[1][1] - t->m[1][0]*t->m[0][1];
+}
+
+static bool
+affine_is_pixel_exact(const struct pixman_f_transform *t)
+{
+	double det;


Reply to: