xf86-video-intel: 9 commits - src/sna/gen2_render.c src/sna/gen3_render.c src/sna/gen4_render.c src/sna/gen5_render.c src/sna/gen6_render.c src/sna/gen7_render.c src/sna/kgem.c src/sna/sna_accel.c src/sna/sna_display.c src/sna/sna_dri.c src/sna/sna_driver.c src/sna/sna.h src/sna/sna_io.c src/sna/sna_render.c src/sna/sna_render.h src/sna/sna_tiling.c src/sna/sna_trapezoids.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Jul 4 16:59:48 PDT 2012


 src/sna/gen2_render.c    |    8 +-
 src/sna/gen3_render.c    |    2 
 src/sna/gen4_render.c    |   15 +++
 src/sna/gen5_render.c    |    2 
 src/sna/gen6_render.c    |   10 +-
 src/sna/gen7_render.c    |   10 +-
 src/sna/kgem.c           |   16 ++--
 src/sna/sna.h            |    6 -
 src/sna/sna_accel.c      |   94 ++++++++++-------------
 src/sna/sna_display.c    |    7 +
 src/sna/sna_dri.c        |  185 ++++++++++++++++++++++++-----------------------
 src/sna/sna_driver.c     |    2 
 src/sna/sna_io.c         |   12 +--
 src/sna/sna_render.c     |    2 
 src/sna/sna_render.h     |    4 -
 src/sna/sna_tiling.c     |    8 +-
 src/sna/sna_trapezoids.c |    4 -
 17 files changed, 200 insertions(+), 187 deletions(-)

New commits:
commit 3c1f58fe45e8f4f18c45733f862ca1f290dde84d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 23:03:44 2012 +0100

    sna: drop an unused ret var
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index a54a80a..ed1d700 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -3531,12 +3531,10 @@ retry:
 uint32_t kgem_bo_flink(struct kgem *kgem, struct kgem_bo *bo)
 {
 	struct drm_gem_flink flink;
-	int ret;
 
 	VG_CLEAR(flink);
 	flink.handle = bo->handle;
-	ret = drmIoctl(kgem->fd, DRM_IOCTL_GEM_FLINK, &flink);
-	if (ret)
+	if (drmIoctl(kgem->fd, DRM_IOCTL_GEM_FLINK, &flink))
 		return 0;
 
 	DBG(("%s: flinked handle=%d to name=%d, marking non-reusable\n",
commit a69a47f94037698a360f8b8611f6f3e58a20ca87
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 22:15:45 2012 +0100

    sna: Fix detection of EIO through throttle
    
    When using drmIoctl, one needs to check the errno for the actual error
    code.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 7f8c89e..a54a80a 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -619,7 +619,10 @@ static bool semaphores_enabled(void)
 
 static bool __kgem_throttle(struct kgem *kgem)
 {
-	return drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL) == -EIO;
+	if (drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_THROTTLE, NULL) == 0)
+		return false;
+
+	return errno == EIO;
 }
 
 static bool is_hw_supported(struct kgem *kgem)
@@ -2067,6 +2070,7 @@ void kgem_throttle(struct kgem *kgem)
 	static int warned;
 
 	kgem->wedged |= __kgem_throttle(kgem);
+	DBG(("%s: wedged=%d\n", __FUNCTION__, kgem->wedged));
 	if (kgem->wedged && !warned) {
 		struct sna *sna = container_of(kgem, struct sna, kgem);
 		xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
commit f2fdb0da83d6208c884ffde2bb30d0a67fc75217
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 21:43:22 2012 +0100

    sna: Use throttle() to confirm a GPU hang
    
    This has two effects. The first is that we confirm that the EIO was
    indeed a GPU hang and not some other form of I/O failure (for example
    swapin). And the second is that it means we also print the warning to
    look for an i915_error_state when we detect a GPU hang.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index 944b8f2..7f8c89e 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -1604,7 +1604,7 @@ static void kgem_commit(struct kgem *kgem)
 		set_domain.write_domain = I915_GEM_DOMAIN_GTT;
 		if (drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain)) {
 			DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
-			kgem->wedged = 1;
+			kgem_throttle(kgem);
 		}
 
 		kgem_retire(kgem);
@@ -1983,7 +1983,7 @@ void _kgem_submit(struct kgem *kgem)
 			}
 			if (ret == -1 && (errno == EIO || errno == EBUSY)) {
 				DBG(("%s: GPU hang detected\n", __FUNCTION__));
-				kgem->wedged = 1;
+				kgem_throttle(kgem);
 				ret = 0;
 			}
 #if !NDEBUG
@@ -2047,7 +2047,7 @@ void _kgem_submit(struct kgem *kgem)
 				ret = drmIoctl(kgem->fd, DRM_IOCTL_I915_GEM_SET_DOMAIN, &set_domain);
 				if (ret == -1) {
 					DBG(("%s: sync: GPU hang detected\n", __FUNCTION__));
-					kgem->wedged = 1;
+					kgem_throttle(kgem);
 				}
 			}
 		}
commit b8c2b34e39c7f2ee2597f8727b9b98c6aac93fb1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 19:53:27 2012 +0100

    sna: Simplify timer execution
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna.h b/src/sna/sna.h
index 8564cfc..218a882 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -217,11 +217,9 @@ struct sna {
 	unsigned watch_flush;
 	unsigned flush;
 
-	OsTimerPtr timer;
+	struct timeval timer_tv;
 	uint32_t timer_expire[NUM_TIMERS];
 	uint16_t timer_active;
-	uint16_t timer_ready;
-	struct timeval timer_tv;
 
 	int vblank_interval;
 
@@ -570,7 +568,7 @@ static inline uint32_t pixmap_size(PixmapPtr pixmap)
 Bool sna_accel_pre_init(struct sna *sna);
 Bool sna_accel_init(ScreenPtr sreen, struct sna *sna);
 void sna_accel_block_handler(struct sna *sna, struct timeval **tv);
-void sna_accel_wakeup_handler(struct sna *sna, fd_set *ready);
+void sna_accel_wakeup_handler(struct sna *sna);
 void sna_accel_watch_flush(struct sna *sna, int enable);
 void sna_accel_close(struct sna *sna);
 void sna_accel_free(struct sna *sna);
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 1f17c00..46a9180 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -3719,8 +3719,6 @@ fallback:
 static int
 source_prefer_gpu(struct sna_pixmap *priv)
 {
-	unsigned flags;
-
 	if (priv == NULL) {
 		DBG(("%s: source unattached, use cpu\n", __FUNCTION__));
 		return 0;
@@ -12246,7 +12244,6 @@ static void sna_accel_disarm_timer(struct sna *sna, int id)
 {
 	DBG(("%s[%d] (time=%ld)\n", __FUNCTION__, id, (long)TIME));
 	sna->timer_active &= ~(1<<id);
-	sna->timer_ready &= ~(1<<id);
 }
 
 static bool has_shadow(struct sna *sna)
@@ -12302,8 +12299,10 @@ static bool sna_accel_do_flush(struct sna *sna)
 		return true;
 
 	if (sna->timer_active & (1<<(FLUSH_TIMER))) {
-		DBG(("%s: flush timer active\n", __FUNCTION__));
-		if (sna->timer_ready & (1<<(FLUSH_TIMER))) {
+		int32_t delta = sna->timer_expire[FLUSH_TIMER] - TIME;
+		DBG(("%s: flush timer active: delta=%d\n",
+		     __FUNCTION__, delta));
+		if (delta <= 3) {
 			DBG(("%s (time=%ld), triggered\n", __FUNCTION__, (long)TIME));
 			sna->timer_expire[FLUSH_TIMER] =
 				TIME + sna->vblank_interval;
@@ -12314,7 +12313,6 @@ static bool sna_accel_do_flush(struct sna *sna)
 			DBG(("%s -- no pending write to scanout\n", __FUNCTION__));
 		} else {
 			sna->timer_active |= 1 << FLUSH_TIMER;
-			sna->timer_ready |= 1 << FLUSH_TIMER;
 			sna->timer_expire[FLUSH_TIMER] =
 				TIME + sna->vblank_interval / 2;
 			DBG(("%s (time=%ld), starting\n", __FUNCTION__, (long)TIME));
@@ -12330,7 +12328,8 @@ static bool sna_accel_do_throttle(struct sna *sna)
 		return false;
 
 	if (sna->timer_active & (1<<(THROTTLE_TIMER))) {
-		if (sna->timer_ready & (1<<(THROTTLE_TIMER))) {
+		int32_t delta = sna->timer_expire[THROTTLE_TIMER] - TIME;
+		if (delta <= 3) {
 			DBG(("%s (time=%ld), triggered\n", __FUNCTION__, (long)TIME));
 			sna->timer_expire[THROTTLE_TIMER] = TIME + 20;
 			return true;
@@ -12341,7 +12340,6 @@ static bool sna_accel_do_throttle(struct sna *sna)
 		} else {
 			DBG(("%s (time=%ld), starting\n", __FUNCTION__, (long)TIME));
 			sna->timer_active |= 1 << THROTTLE_TIMER;
-			sna->timer_ready |= 1 << THROTTLE_TIMER;
 			sna->timer_expire[THROTTLE_TIMER] = TIME + 20;
 		}
 	}
@@ -12352,7 +12350,8 @@ static bool sna_accel_do_throttle(struct sna *sna)
 static bool sna_accel_do_expire(struct sna *sna)
 {
 	if (sna->timer_active & (1<<(EXPIRE_TIMER))) {
-		if (sna->timer_ready & (1<<(EXPIRE_TIMER))) {
+		int32_t delta = sna->timer_expire[EXPIRE_TIMER] - TIME;
+		if (delta <= 3) {
 			DBG(("%s (time=%ld), triggered\n", __FUNCTION__, (long)TIME));
 			sna->timer_expire[EXPIRE_TIMER] =
 				TIME + MAX_INACTIVE_TIME * 1000;
@@ -12361,7 +12360,6 @@ static bool sna_accel_do_expire(struct sna *sna)
 	} else {
 		if (sna->kgem.need_expire) {
 			sna->timer_active |= 1 << EXPIRE_TIMER;
-			sna->timer_ready |= 1 << EXPIRE_TIMER;
 			sna->timer_expire[EXPIRE_TIMER] =
 				TIME + MAX_INACTIVE_TIME * 1000;
 			DBG(("%s (time=%ld), starting\n", __FUNCTION__, (long)TIME));
@@ -12374,7 +12372,8 @@ static bool sna_accel_do_expire(struct sna *sna)
 static bool sna_accel_do_inactive(struct sna *sna)
 {
 	if (sna->timer_active & (1<<(INACTIVE_TIMER))) {
-		if (sna->timer_ready & (1<<(INACTIVE_TIMER))) {
+		int32_t delta = sna->timer_expire[INACTIVE_TIMER] - TIME;
+		if (delta <= 3) {
 			sna->timer_expire[INACTIVE_TIMER] =
 				TIME + 120 * 1000;
 			DBG(("%s (time=%ld), triggered\n", __FUNCTION__, (long)TIME));
@@ -12383,7 +12382,6 @@ static bool sna_accel_do_inactive(struct sna *sna)
 	} else {
 		if (!list_is_empty(&sna->active_pixmaps)) {
 			sna->timer_active |= 1 << INACTIVE_TIMER;
-			sna->timer_ready |= 1 << INACTIVE_TIMER;
 			sna->timer_expire[INACTIVE_TIMER] =
 				TIME + 120 * 1000;
 			DBG(("%s (time=%ld), starting\n", __FUNCTION__, (long)TIME));
@@ -12393,33 +12391,25 @@ static bool sna_accel_do_inactive(struct sna *sna)
 	return false;
 }
 
-static CARD32 sna_timeout(OsTimerPtr timer, CARD32 now, pointer arg)
+static int32_t sna_timeout(struct sna *sna)
 {
-	struct sna *sna = arg;
-	int32_t next = 0;
-	uint32_t active;
+	int32_t now = TIME, next = 0;
 	int i;
 
-	DBG(("%s: now=%d, active=%08x, ready=%08x\n",
-	     __FUNCTION__, (int)now, sna->timer_active, sna->timer_ready));
-	active = sna->timer_active & ~sna->timer_ready;
-	if (active == 0)
-		return 0;
-
+	DBG(("%s: now=%d, active=%08x\n",
+	     __FUNCTION__, (int)now, sna->timer_active));
 	for (i = 0; i < NUM_TIMERS; i++) {
-		if (active & (1 << i)) {
+		if (sna->timer_active & (1 << i)) {
 			int32_t delta = sna->timer_expire[i] - now;
 			DBG(("%s: timer[%d] expires in %d [%d]\n",
 			     __FUNCTION__, i, delta, sna->timer_expire[i]));
-			if (delta <= 3)
-				sna->timer_ready |= 1 << i;
-			else if (next == 0 || delta < next)
+			if (next == 0 || delta < next)
 				next = delta;
 		}
 	}
 
-	DBG(("%s: active=%08x, ready=%08x, next=+%d\n",
-	     __FUNCTION__, sna->timer_active, sna->timer_ready, next));
+	DBG(("%s: active=%08x, next=+%d\n",
+	     __FUNCTION__, sna->timer_active, next));
 	return next;
 }
 
@@ -12596,7 +12586,6 @@ static void sna_accel_debug_memory(struct sna *sna) { }
 
 Bool sna_accel_pre_init(struct sna *sna)
 {
-	sna->timer = TimerSet(NULL, 0, 0, sna_timeout, sna);
 	return TRUE;
 }
 
@@ -12741,6 +12730,8 @@ void sna_accel_close(struct sna *sna)
 
 void sna_accel_block_handler(struct sna *sna, struct timeval **tv)
 {
+	UpdateCurrentTimeIf();
+
 	if (sna->kgem.nbatch && kgem_is_idle(&sna->kgem)) {
 		DBG(("%s: GPU idle, flushing\n", __FUNCTION__));
 		_kgem_submit(&sna->kgem);
@@ -12776,14 +12767,12 @@ void sna_accel_block_handler(struct sna *sna, struct timeval **tv)
 		sna->watch_flush = 0;
 	}
 
-	if (sna->timer_ready) {
+	if (sna->timer_active) {
 		int32_t timeout;
 
-		DBG(("%s: evaluating timers, ready=%x\n",
-		     __FUNCTION__, sna->timer_ready));
-		sna->timer_ready = 0;
-		timeout = sna_timeout(sna->timer, TIME, sna);
-		TimerSet(sna->timer, 0, timeout, sna_timeout, sna);
+		DBG(("%s: evaluating timers, active=%x\n",
+		     __FUNCTION__, sna->timer_active));
+		timeout = sna_timeout(sna);
 		if (timeout) {
 			if (*tv == NULL) {
 				*tv = &sna->timer_tv;
@@ -12798,9 +12787,10 @@ set_tv:
 	}
 }
 
-void sna_accel_wakeup_handler(struct sna *sna, fd_set *ready)
+void sna_accel_wakeup_handler(struct sna *sna)
 {
 	DBG(("%s\n", __FUNCTION__));
+
 	if (sna->kgem.need_retire)
 		kgem_retire(&sna->kgem);
 	if (!sna->mode.shadow_active && !sna->kgem.need_retire) {
diff --git a/src/sna/sna_driver.c b/src/sna/sna_driver.c
index f7eeca5..6476d1a 100644
--- a/src/sna/sna_driver.c
+++ b/src/sna/sna_driver.c
@@ -596,7 +596,7 @@ sna_wakeup_handler(WAKEUPHANDLER_ARGS_DECL)
 
 	sna->WakeupHandler(WAKEUPHANDLER_ARGS);
 
-	sna_accel_wakeup_handler(sna, read_mask);
+	sna_accel_wakeup_handler(sna);
 
 	if (FD_ISSET(sna->kgem.fd, (fd_set*)read_mask))
 		sna_mode_wakeup(sna);
commit 844ab84c64fde38db315787e16a9f7f674d0f88c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 17:58:27 2012 +0100

    sna: Fix leak around ENOMEM error path in sna_copy_boxes
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 1919b2e..1f17c00 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -3974,7 +3974,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 						       src->depth,
 						       KGEM_BUFFER_WRITE_INPLACE);
 			if (tmp == NullPixmap)
-				return;
+				goto out;
 
 			dx = -region.extents.x1;
 			dy = -region.extents.y1;
commit 54ee41bf05e328ed2f2cd2a64c21afe3efe2556a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 17:40:58 2012 +0100

    sna: Pass a hint to the backends when using copy_boxes for readback
    
    If we expect to only emit this set of copy_boxes() and then submit the
    batch, we would prefer to use the BLT for its lower latency.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index 5fd995b..b41c386 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -2409,7 +2409,7 @@ static inline Bool prefer_blt_fill(struct sna *sna)
 #endif
 }
 
-static inline Bool prefer_blt_copy(struct sna *sna)
+static inline Bool prefer_blt_copy(struct sna *sna, unsigned flags)
 {
 #if PREFER_BLT_COPY
 	return true;
@@ -2864,7 +2864,7 @@ static Bool
 gen2_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-		       const BoxRec *box, int n)
+		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
@@ -2882,7 +2882,7 @@ gen2_render_copy_boxes(struct sna *sna, uint8_t alu,
 	DBG(("%s (%d, %d)->(%d, %d) x %d\n",
 	     __FUNCTION__, src_dx, src_dy, dst_dx, dst_dy, n));
 
-	if (prefer_blt_copy(sna) &&
+	if (prefer_blt_copy(sna, flags) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
@@ -3048,7 +3048,7 @@ gen2_render_copy(struct sna *sna, uint8_t alu,
 #endif
 
 	/* Prefer to use the BLT */
-	if (prefer_blt_copy(sna) &&
+	if (prefer_blt_copy(sna, 0) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
 	    sna_blt_copy(sna, alu,
 			 src_bo, dst_bo,
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 63bbd76..cfc8c63 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -4040,7 +4040,7 @@ static Bool
 gen3_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-		       const BoxRec *box, int n)
+		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index c3a8204..c577536 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -2576,11 +2576,22 @@ gen4_render_copy_one(struct sna *sna,
 	FLUSH(op);
 }
 
+static inline bool prefer_blt_copy(struct sna *sna, unsigned flags)
+{
+#if PREFER_BLT
+	return true;
+	(void)sna;
+#else
+	return sna->kgem.mode != KGEM_RENDER;
+#endif
+	(void)flags;
+}
+
 static Bool
 gen4_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-		       const BoxRec *box, int n)
+		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
@@ -2597,7 +2608,7 @@ gen4_render_copy_boxes(struct sna *sna, uint8_t alu,
 				  box, n);
 #endif
 
-	if (prefer_blt(sna) &&
+	if (prefer_blt_copy(sna, flags) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 46a37a0..49cc17e 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -2909,7 +2909,7 @@ static Bool
 gen5_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-		       const BoxRec *box, int n)
+		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 81fad35..778a072 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -3238,9 +3238,11 @@ static bool prefer_blt_bo(struct sna *sna,
 
 static inline bool prefer_blt_copy(struct sna *sna,
 				   PixmapPtr src, struct kgem_bo *src_bo,
-				   PixmapPtr dst, struct kgem_bo *dst_bo)
+				   PixmapPtr dst, struct kgem_bo *dst_bo,
+				   unsigned flags)
 {
 	return (sna->kgem.ring == KGEM_BLT ||
+		(flags & COPY_LAST && sna->kgem.mode == KGEM_NONE) ||
 		prefer_blt_bo(sna, src, src_bo) ||
 		prefer_blt_bo(sna, dst, dst_bo));
 }
@@ -3280,7 +3282,7 @@ static Bool
 gen6_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-		       const BoxRec *box, int n)
+		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
@@ -3302,7 +3304,7 @@ gen6_render_copy_boxes(struct sna *sna, uint8_t alu,
 		      dst_bo, dst_dx, dst_dy,
 		      box, n)));
 
-	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo) &&
+	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo, flags) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
@@ -3537,7 +3539,7 @@ gen6_render_copy(struct sna *sna, uint8_t alu,
 	     src->drawable.width, src->drawable.height,
 	     dst->drawable.width, dst->drawable.height));
 
-	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo) &&
+	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo, 0) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
 	    sna_blt_copy(sna, alu,
 			 src_bo, dst_bo,
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index d303286..f9b2e9e 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -3322,9 +3322,11 @@ static bool prefer_blt_bo(struct sna *sna,
 
 static inline bool prefer_blt_copy(struct sna *sna,
 				   PixmapPtr src, struct kgem_bo *src_bo,
-				   PixmapPtr dst, struct kgem_bo *dst_bo)
+				   PixmapPtr dst, struct kgem_bo *dst_bo,
+				   unsigned flags)
 {
 	return (sna->kgem.ring == KGEM_BLT ||
+		(flags & COPY_LAST && sna->kgem.mode == KGEM_NONE) ||
 		prefer_blt_bo(sna, src, src_bo) ||
 		prefer_blt_bo(sna, dst, dst_bo));
 }
@@ -3364,7 +3366,7 @@ static Bool
 gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
 		       PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 		       PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-		       const BoxRec *box, int n)
+		       const BoxRec *box, int n, unsigned flags)
 {
 	struct sna_composite_op tmp;
 
@@ -3386,7 +3388,7 @@ gen7_render_copy_boxes(struct sna *sna, uint8_t alu,
 		      dst_bo, dst_dx, dst_dy,
 		      box, n)));
 
-	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo) &&
+	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo, flags) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
 	    sna_blt_copy_boxes(sna, alu,
 			       src_bo, src_dx, src_dy,
@@ -3644,7 +3646,7 @@ gen7_render_copy(struct sna *sna, uint8_t alu,
 	     src->drawable.width, src->drawable.height,
 	     dst->drawable.width, dst->drawable.height));
 
-	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo) &&
+	if (prefer_blt_copy(sna, src, src_bo, dst, dst_bo, 0) &&
 	    sna_blt_compare_depth(&src->drawable, &dst->drawable) &&
 	    sna_blt_copy(sna, alu,
 			 src_bo, dst_bo,
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 537b287..1919b2e 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -594,7 +594,7 @@ struct kgem_bo *sna_pixmap_change_tiling(PixmapPtr pixmap, uint32_t tiling)
 	if (!sna->render.copy_boxes(sna, GXcopy,
 				    pixmap, priv->gpu_bo, 0, 0,
 				    pixmap, bo, 0, 0,
-				    &box, 1)) {
+				    &box, 1, 0)) {
 		DBG(("%s: copy failed\n", __FUNCTION__));
 		kgem_bo_destroy(&sna->kgem, bo);
 		return NULL;
@@ -1232,7 +1232,7 @@ skip_inplace_map:
 				ok = sna->render.copy_boxes(sna, GXcopy,
 							    pixmap, priv->gpu_bo, 0, 0,
 							    pixmap, priv->cpu_bo, 0, 0,
-							    box, n);
+							    box, n, COPY_LAST);
 			if (!ok)
 				sna_read_boxes(sna,
 					       priv->gpu_bo, 0, 0,
@@ -1690,7 +1690,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 				ok = sna->render.copy_boxes(sna, GXcopy,
 							    pixmap, priv->gpu_bo, 0, 0,
 							    pixmap, priv->cpu_bo, 0, 0,
-							    box, n);
+							    box, n, COPY_LAST);
 			if (!ok)
 				sna_read_boxes(sna,
 					       priv->gpu_bo, 0, 0,
@@ -1798,7 +1798,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 						ok = sna->render.copy_boxes(sna, GXcopy,
 									    pixmap, priv->gpu_bo, 0, 0,
 									    pixmap, priv->cpu_bo, 0, 0,
-									    box, n);
+									    box, n, COPY_LAST);
 
 					if (!ok)
 						sna_read_boxes(sna,
@@ -1823,7 +1823,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 					ok = sna->render.copy_boxes(sna, GXcopy,
 								    pixmap, priv->gpu_bo, 0, 0,
 								    pixmap, priv->cpu_bo, 0, 0,
-								    box, n);
+								    box, n, COPY_LAST);
 				if (!ok)
 					sna_read_boxes(sna,
 						       priv->gpu_bo, 0, 0,
@@ -1848,7 +1848,7 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 						ok = sna->render.copy_boxes(sna, GXcopy,
 									    pixmap, priv->gpu_bo, 0, 0,
 									    pixmap, priv->cpu_bo, 0, 0,
-									    box, n);
+									    box, n, COPY_LAST);
 					if (!ok)
 						sna_read_boxes(sna,
 							       priv->gpu_bo, 0, 0,
@@ -2096,7 +2096,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 				ok = sna->render.copy_boxes(sna, GXcopy,
 							    pixmap, priv->cpu_bo, 0, 0,
 							    pixmap, priv->gpu_bo, 0, 0,
-							    box, n);
+							    box, n, 0);
 			if (!ok) {
 				if (pixmap->devPrivate.ptr == NULL) {
 					assert(priv->stride && priv->ptr);
@@ -2134,7 +2134,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 			ok = sna->render.copy_boxes(sna, GXcopy,
 						    pixmap, priv->cpu_bo, 0, 0,
 						    pixmap, priv->gpu_bo, 0, 0,
-						    box, 1);
+						    box, 1, 0);
 		if (!ok) {
 			if (pixmap->devPrivate.ptr == NULL) {
 				assert(priv->stride && priv->ptr);
@@ -2163,7 +2163,7 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, const BoxRec *box, unsigned int fl
 			ok = sna->render.copy_boxes(sna, GXcopy,
 						    pixmap, priv->cpu_bo, 0, 0,
 						    pixmap, priv->gpu_bo, 0, 0,
-						    box, n);
+						    box, n,0);
 		if (!ok) {
 			if (pixmap->devPrivate.ptr == NULL) {
 				assert(priv->stride && priv->ptr);
@@ -2641,7 +2641,7 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap, unsigned flags)
 			ok = sna->render.copy_boxes(sna, GXcopy,
 						    pixmap, priv->cpu_bo, 0, 0,
 						    pixmap, priv->gpu_bo, 0, 0,
-						    box, n);
+						    box, n, 0);
 		if (!ok) {
 			if (pixmap->devPrivate.ptr == NULL) {
 				assert(priv->stride && priv->ptr);
@@ -3657,7 +3657,7 @@ sna_self_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 		if (!sna->render.copy_boxes(sna, alu,
 					    pixmap, priv->gpu_bo, dx, dy,
 					    pixmap, priv->gpu_bo, tx, ty,
-					    box, n)) {
+					    box, n, 0)) {
 			DBG(("%s: fallback - accelerated copy boxes failed\n",
 			     __FUNCTION__));
 			goto fallback;
@@ -3874,7 +3874,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 			if (!sna->render.copy_boxes(sna, alu,
 						    src_pixmap, src_priv->gpu_bo, src_dx, src_dy,
 						    dst_pixmap, bo, dst_dx, dst_dy,
-						    box, n)) {
+						    box, n, 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
 				goto fallback;
@@ -3909,7 +3909,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 			if (!sna->render.copy_boxes(sna, alu,
 						    src_pixmap, src_priv->gpu_bo, src_dx, src_dy,
 						    dst_pixmap, bo, dst_dx, dst_dy,
-						    box, n)) {
+						    box, n, 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
 				goto fallback;
@@ -3945,7 +3945,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 			if (!sna->render.copy_boxes(sna, alu,
 						    src_pixmap, src_priv->cpu_bo, src_dx, src_dy,
 						    dst_pixmap, bo, dst_dx, dst_dy,
-						    box, n)) {
+						    box, n, 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
 				goto fallback;
@@ -4005,7 +4005,7 @@ sna_copy_boxes(DrawablePtr src, DrawablePtr dst, GCPtr gc,
 			if (!sna->render.copy_boxes(sna, alu,
 						    tmp, sna_pixmap_get_bo(tmp), dx, dy,
 						    dst_pixmap, bo, dst_dx, dst_dy,
-						    box, n)) {
+						    box, n, 0)) {
 				DBG(("%s: fallback - accelerated copy boxes failed\n",
 				     __FUNCTION__));
 				tmp->drawable.pScreen->DestroyPixmap(tmp);
diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index f1a0b84..f59eed5 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -814,7 +814,7 @@ void sna_copy_fbcon(struct sna *sna)
 	ok = sna->render.copy_boxes(sna, GXcopy,
 				    scratch, bo, sx, sy,
 				    sna->front, priv->gpu_bo, dx, dy,
-				    &box, 1);
+				    &box, 1, 0);
 	if (!DAMAGE_IS_ALL(priv->gpu_damage))
 		sna_damage_add_box(&priv->gpu_damage, &box);
 
@@ -2780,7 +2780,7 @@ sna_crtc_redisplay(xf86CrtcPtr crtc, RegionPtr region)
 		if (sna->render.copy_boxes(sna, GXcopy,
 					   sna->front, sna_pixmap_get_bo(sna->front), 0, 0,
 					   &tmp, sna_crtc->bo, -tx, -ty,
-					   REGION_RECTS(region), REGION_NUM_RECTS(region)))
+					   REGION_RECTS(region), REGION_NUM_RECTS(region), 0))
 			return;
 	}
 
@@ -2909,7 +2909,8 @@ disable:
 					     sna->front, new, 0, 0,
 					     sna->front, old, 0, 0,
 					     REGION_RECTS(region),
-					     REGION_NUM_RECTS(region));
+					     REGION_NUM_RECTS(region),
+					     COPY_LAST);
 		kgem_submit(&sna->kgem);
 
 		sna_pixmap(sna->front)->gpu_bo = old;
diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 4519f17..a10efc7 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -568,7 +568,7 @@ sna_dri_copy_to_front(struct sna *sna, DrawablePtr draw, RegionPtr region,
 	sna->render.copy_boxes(sna, GXcopy,
 			       (PixmapPtr)draw, src_bo, -draw->x, -draw->y,
 			       pixmap, dst_bo, dx, dy,
-			       boxes, n);
+			       boxes, n, COPY_LAST);
 
 	DBG(("%s: flushing? %d\n", __FUNCTION__, flush));
 	if (flush) { /* STAT! */
@@ -654,7 +654,7 @@ sna_dri_copy_from_front(struct sna *sna, DrawablePtr draw, RegionPtr region,
 	sna->render.copy_boxes(sna, GXcopy,
 			       pixmap, src_bo, dx, dy,
 			       (PixmapPtr)draw, dst_bo, -draw->x, -draw->y,
-			       boxes, n);
+			       boxes, n, COPY_LAST);
 
 	if (region == &clip)
 		pixman_region_fini(&clip);
@@ -697,7 +697,7 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
 	sna->render.copy_boxes(sna, GXcopy,
 			       (PixmapPtr)draw, src_bo, 0, 0,
 			       (PixmapPtr)draw, dst_bo, 0, 0,
-			       boxes, n);
+			       boxes, n, COPY_LAST);
 
 	if (region == &clip)
 		pixman_region_fini(&clip);
diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c
index 8d04548..ffa86b1 100644
--- a/src/sna/sna_io.c
+++ b/src/sna/sna_io.c
@@ -276,7 +276,7 @@ fallback:
 					if (!sna->render.copy_boxes(sna, GXcopy,
 								    dst, src_bo, src_dx, src_dy,
 								    &tmp, dst_bo, -tile.x1, -tile.y1,
-								    clipped, c-clipped)) {
+								    clipped, c-clipped, COPY_LAST)) {
 						kgem_bo_destroy(&sna->kgem, dst_bo);
 						if (clipped != stack)
 							free(clipped);
@@ -316,7 +316,7 @@ fallback:
 			if (!sna->render.copy_boxes(sna, GXcopy,
 						    dst, src_bo, src_dx, src_dy,
 						    &tmp, dst_bo, -extents.x1, -extents.y1,
-						    box, nbox)) {
+						    box, nbox, COPY_LAST)) {
 				kgem_bo_destroy(&sna->kgem, dst_bo);
 				goto fallback;
 			}
@@ -689,7 +689,7 @@ tile:
 						n = sna->render.copy_boxes(sna, GXcopy,
 									   &tmp, src_bo, -tile.x1, -tile.y1,
 									   dst, dst_bo, dst_dx, dst_dy,
-									   clipped, c - clipped);
+									   clipped, c - clipped, 0);
 					else
 						n = 1;
 
@@ -736,7 +736,7 @@ tile:
 			n = sna->render.copy_boxes(sna, GXcopy,
 						   &tmp, src_bo, -extents.x1, -extents.y1,
 						   dst, dst_bo, dst_dx, dst_dy,
-						   box, nbox);
+						   box, nbox, 0);
 
 			kgem_bo_destroy(&sna->kgem, src_bo);
 
@@ -973,7 +973,7 @@ fallback:
 		n = sna->render.copy_boxes(sna, GXcopy,
 					   &tmp, src_bo, -extents.x1, -extents.y1,
 					   dst, dst_bo, dst_dx, dst_dy,
-					   box, nbox);
+					   box, nbox, 0);
 
 		kgem_bo_destroy(&sna->kgem, src_bo);
 
@@ -1144,7 +1144,7 @@ indirect_replace(struct sna *sna,
 	ret = sna->render.copy_boxes(sna, GXcopy,
 				     pixmap, src_bo, 0, 0,
 				     pixmap, bo, 0, 0,
-				     &box, 1);
+				     &box, 1, 0);
 
 	kgem_bo_destroy(kgem, src_bo);
 
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index a072994..c22965c 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1167,7 +1167,7 @@ sna_render_picture_extract(struct sna *sna,
 			if (!sna->render.copy_boxes(sna, GXcopy,
 						    pixmap, src_bo, 0, 0,
 						    &tmp, bo, -box.x1, -box.y1,
-						    &box, 1)) {
+						    &box, 1, 0)) {
 				kgem_bo_destroy(&sna->kgem, bo);
 				bo = NULL;
 			}
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 1cc3af1..0eb7e90 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -237,7 +237,9 @@ struct sna_render {
 	Bool (*copy_boxes)(struct sna *sna, uint8_t alu,
 			   PixmapPtr src, struct kgem_bo *src_bo, int16_t src_dx, int16_t src_dy,
 			   PixmapPtr dst, struct kgem_bo *dst_bo, int16_t dst_dx, int16_t dst_dy,
-			   const BoxRec *box, int n);
+			   const BoxRec *box, int n, unsigned flags);
+#define COPY_LAST 0x1
+
 	Bool (*copy)(struct sna *sna, uint8_t alu,
 		     PixmapPtr src, struct kgem_bo *src_bo,
 		     PixmapPtr dst, struct kgem_bo *dst_bo,
diff --git a/src/sna/sna_tiling.c b/src/sna/sna_tiling.c
index 27a9dc8..b20eceb 100644
--- a/src/sna/sna_tiling.c
+++ b/src/sna/sna_tiling.c
@@ -659,7 +659,7 @@ sna_tiling_fill_boxes(struct sna *sna,
 				if (!sna->render.copy_boxes(sna, GXcopy,
 							     dst, dst_bo, 0, 0,
 							     &tmp, bo, -dx, -dy,
-							     REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
+							     REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0))
 					goto err;
 
 				RegionTranslate(&this, -dx, -dy);
@@ -671,7 +671,7 @@ sna_tiling_fill_boxes(struct sna *sna,
 				if (!sna->render.copy_boxes(sna, GXcopy,
 							     &tmp, bo, 0, 0,
 							     dst, dst_bo, dx, dy,
-							     REGION_RECTS(&this), REGION_NUM_RECTS(&this)))
+							     REGION_RECTS(&this), REGION_NUM_RECTS(&this), 0))
 					goto err;
 
 				kgem_bo_destroy(&sna->kgem, bo);
@@ -898,11 +898,11 @@ sna_tiling_copy_boxes(struct sna *sna, uint8_t alu,
 			i = (sna->render.copy_boxes(sna, GXcopy,
 						    src, src_bo, src_dx, src_dy,
 						    &p, tmp_bo, -tile.x1, -tile.y1,
-						    clipped, c - clipped) &&
+						    clipped, c - clipped, 0) &&
 			     sna->render.copy_boxes(sna, alu,
 						    &p, tmp_bo, -tile.x1, -tile.y1,
 						    dst, dst_bo, dst_dx, dst_dy,
-						    clipped, c - clipped));
+						    clipped, c - clipped, 0));
 
 			kgem_bo_destroy(&sna->kgem, tmp_bo);
 
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 36defa1..d83c083 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -5779,7 +5779,7 @@ trap_mask_converter(PicturePtr picture,
 	sna->render.copy_boxes(sna, GXcopy,
 			       scratch, sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
 			       pixmap, priv->gpu_bo, x, y,
-			       &extents, 1);
+			       &extents, 1, 0);
 	mark_damaged(pixmap, priv, &extents ,x, y);
 
 	screen->DestroyPixmap(scratch);
@@ -5857,7 +5857,7 @@ trap_upload(PicturePtr picture,
 	sna->render.copy_boxes(sna, GXcopy,
 			       scratch, sna_pixmap_get_bo(scratch), -extents.x1, -extents.x1,
 			       pixmap, priv->gpu_bo, x, y,
-			       &extents, 1);
+			       &extents, 1, 0);
 	mark_damaged(pixmap, priv, &extents, x, y);
 
 	screen->DestroyPixmap(scratch);
commit d36623aaebdc454bd281f34332edcad5d94f34c0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 13:55:25 2012 +0100

    sna/dri: Remove broken code for buffer xchg from AsyncSwap
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 44015e4..4519f17 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -46,13 +46,17 @@ USE OR OTHER DEALINGS IN THE SOFTWARE.
 #include <i915_drm.h>
 #include <dri2.h>
 
+#if DEBUG_DRI
+#undef DBG
+#define DBG(x) ErrorF x
+#endif
+
 #if DRI2INFOREC_VERSION <= 2
 #error DRI2 version supported by the Xserver is too old
 #endif
 
-#if DEBUG_DRI
-#undef DBG
-#define DBG(x) ErrorF x
+#if DRI2INFOREC_VERSION < 9
+#define USE_ASYNC_SWAP 0
 #endif
 
 #define COLOR_PREFER_TILING_Y 0
@@ -1468,7 +1472,7 @@ static void sna_dri_flip_event(struct sna *sna,
 			sna_dri_frame_event_info_free(sna, flip);
 		break;
 
-#if USE_ASYNC_SWAP && DRI2INFOREC_VERSION >= 7
+#if USE_ASYNC_SWAP
 	case DRI2_ASYNC_FLIP:
 		DBG(("%s: async swap flip completed on pipe %d, pending? %d, new? %d\n",
 		     __FUNCTION__, flip->pipe,
@@ -1509,7 +1513,7 @@ finish_async_flip:
 
 			DBG(("%s: async flip completed\n", __FUNCTION__));
 			sna->dri.flip_pending = NULL;
-			sna_dri_frame_event_info_free(fsna, lip);
+			sna_dri_frame_event_info_free(sna, flip);
 		}
 		break;
 #endif
@@ -2028,20 +2032,7 @@ blit_fallback:
 	return TRUE;
 }
 
-#if USE_ASYNC_SWAP && DRI2INFOREC_VERSION >= 7
-static void
-sna_dri_exchange_attachment(DRI2BufferPtr front, DRI2BufferPtr back)
-{
-	int tmp;
-
-	DBG(("%s(%d <--> %d)\n",
-	     __FUNCTION__, front->attachment, back->attachment));
-
-	tmp = front->attachment;
-	front->attachment = back->attachment;
-	back->attachment = tmp;
-}
-
+#if USE_ASYNC_SWAP
 static Bool
 sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 		   DRI2BufferPtr front, DRI2BufferPtr back,
@@ -2054,34 +2045,23 @@ sna_dri_async_swap(ClientPtr client, DrawablePtr draw,
 
 	DBG(("%s()\n", __FUNCTION__));
 
-	if (!sna->scrn->vtSema) {
-		PixmapPtr pixmap;
-
-exchange:
-		DBG(("%s: unattached, exchange pixmaps\n", __FUNCTION__));
-
-		pixmap = get_drawable_pixmap(draw);
-		set_bo(pixmap, get_private(back)->bo);
-		sna_dri_exchange_attachment(front, back);
-		get_private(back)->pixmap = pixmap;
-		get_private(front)->pixmap = NULL;
-
-		DRI2SwapComplete(client, draw, 0, 0, 0,
-				 DRI2_EXCHANGE_COMPLETE, func, data);
-		return TRUE;
-	}
-
 	if (!can_flip(sna, draw, front, back)) {
 blit:
-		DBG(("%s: unable to flip, so blit\n", __FUNCTION__));
+		if (can_exchange(sna, draw, front, back)) {
+			DBG(("%s: unable to flip, so xchg\n", __FUNCTION__));
+			sna_dri_exchange_buffers(draw, front, back);
+			name = DRI2_EXCHANGE_COMPLETE;
+		} else {
+			DBG(("%s: unable to flip, so blit\n", __FUNCTION__));
+			sna_dri_copy_to_front(sna, draw, NULL,
+					      get_private(front)->bo,
+					      get_private(back)->bo,
+					      false);
+			name = DRI2_BLIT_COMPLETE;
+		}
 
-		sna_dri_copy_to_front(sna, draw, NULL,
-				      get_private(front)->bo,
-				      get_private(back)->bo,
-				      false);
-		DRI2SwapComplete(client, draw, 0, 0, 0,
-				 DRI2_BLIT_COMPLETE, func, data);
-		return FALSE;
+		DRI2SwapComplete(client, draw, 0, 0, 0, name, func, data);
+		return name == DRI2_EXCHANGE_COMPLETE;
 	}
 
 	bo = NULL;
@@ -2091,7 +2071,7 @@ blit:
 	if (info == NULL) {
 		int pipe = sna_dri_get_pipe(draw);
 		if (pipe == -1)
-			goto exchange;
+			goto blit;
 
 		DBG(("%s: no pending flip, so updating scanout\n",
 		     __FUNCTION__));
@@ -2100,7 +2080,6 @@ blit:
 		if (!info)
 			goto blit;
 
-		info->sna = sna;
 		info->client = client;
 		info->type = DRI2_ASYNC_FLIP;
 		info->pipe = pipe;
@@ -2393,8 +2372,8 @@ Bool sna_dri_open(struct sna *sna, ScreenPtr screen)
 	info.ReuseBufferNotify = NULL;
 #endif
 
-#if USE_AYSYNC_SWAP && DRI2INFOREC_VERSION >= 7
-	info.version = 7;
+#if USE_ASYNC_SWAP
+	info.version = 9;
 	info.AsyncSwap = sna_dri_async_swap;
 #endif
 
commit 0bdb4d0d3693df007a6cfc9a75bb0deddd812d53
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 13:12:43 2012 +0100

    sna/dri: Fixup blit fallback path to use xchg when possible
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index db03f77..44015e4 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -1767,6 +1767,7 @@ sna_dri_immediate_xchg(struct sna *sna,
 			priv->chain->chain = info;
 		}
 	} else {
+		sna_dri_exchange_buffers(draw, info->front, info->back);
 		DRI2SwapComplete(info->client, draw, 0, 0, 0,
 				 DRI2_EXCHANGE_COMPLETE,
 				 info->event_complete,
@@ -1928,7 +1929,7 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 
 	info->type = swap_type;
 	if (divisor == 0) {
-		if (can_exchange(sna, draw, info->front, info->back))
+		if (can_exchange(sna, draw, front, back))
 			sna_dri_immediate_xchg(sna, draw, info);
 		else
 			sna_dri_immediate_blit(sna, draw, info);
@@ -2008,14 +2009,21 @@ sna_dri_schedule_swap(ClientPtr client, DrawablePtr draw, DRI2BufferPtr front,
 	return TRUE;
 
 blit_fallback:
-	DBG(("%s -- blit\n", __FUNCTION__));
-	sna_dri_copy_to_front(sna, draw, NULL,
-			      get_private(front)->bo,
-			      get_private(back)->bo,
-			      false);
+	if (can_exchange(sna, draw, front, back)) {
+		DBG(("%s -- xchg\n", __FUNCTION__));
+		sna_dri_exchange_buffers(draw, front, back);
+		pipe = DRI2_EXCHANGE_COMPLETE;
+	} else {
+		DBG(("%s -- blit\n", __FUNCTION__));
+		sna_dri_copy_to_front(sna, draw, NULL,
+				      get_private(front)->bo,
+				      get_private(back)->bo,
+				      false);
+		pipe = DRI2_BLIT_COMPLETE;
+	}
 	if (info)
 		sna_dri_frame_event_info_free(sna, info);
-	DRI2SwapComplete(client, draw, 0, 0, 0, DRI2_BLIT_COMPLETE, func, data);
+	DRI2SwapComplete(client, draw, 0, 0, 0, pipe, func, data);
 	*target_msc = 0; /* offscreen, so zero out target vblank count */
 	return TRUE;
 }
commit aeeed323f9081875a804ae19fb356bee2a61e7b0
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jul 4 11:52:27 2012 +0100

    sna/dri: Select the appropriate copy engine based on the current src ring
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_dri.c b/src/sna/sna_dri.c
index 93e24b8..db03f77 100644
--- a/src/sna/sna_dri.c
+++ b/src/sna/sna_dri.c
@@ -436,6 +436,53 @@ static void set_bo(PixmapPtr pixmap, struct kgem_bo *bo)
 	DamageRegionProcessPending(&pixmap->drawable);
 }
 
+static void sna_dri_select_mode(struct sna *sna, struct kgem_bo *src, bool sync)
+{
+	struct drm_i915_gem_busy busy;
+
+	if (sna->kgem.gen < 60)
+		return;
+
+	if (sync) {
+		DBG(("%s: sync, force RENDER ring\n", __FUNCTION__));
+		kgem_set_mode(&sna->kgem, KGEM_RENDER);
+		return;
+	}
+
+	if (sna->kgem.mode != KGEM_NONE) {
+		DBG(("%s: busy, not switching\n", __FUNCTION__));
+		return;
+	}
+
+	VG_CLEAR(busy);
+	busy.handle = src->handle;
+	if (drmIoctl(sna->kgem.fd, DRM_IOCTL_I915_GEM_BUSY, &busy))
+		return;
+
+	DBG(("%s: src busy?=%x\n", __FUNCTION__, busy.busy));
+	if (busy.busy == 0) {
+		DBG(("%s: src is idle, using defaults\n", __FUNCTION__));
+		return;
+	}
+
+	/* Sandybridge introduced a separate ring which it uses to
+	 * perform blits. Switching rendering between rings incurs
+	 * a stall as we wait upon the old ring to finish and
+	 * flush its render cache before we can proceed on with
+	 * the operation on the new ring.
+	 *
+	 * As this buffer, we presume, has just been written to by
+	 * the DRI client using the RENDER ring, we want to perform
+	 * our operation on the same ring, and ideally on the same
+	 * ring as we will flip from (which should be the RENDER ring
+	 * as well).
+	 */
+	if ((busy.busy & 0xffff0000) == 0 || busy.busy & (1 << 16))
+		kgem_set_mode(&sna->kgem, KGEM_RENDER);
+	else
+		kgem_set_mode(&sna->kgem, KGEM_BLT);
+}
+
 static struct kgem_bo *
 sna_dri_copy_to_front(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		      struct kgem_bo *dst_bo, struct kgem_bo *src_bo,
@@ -502,21 +549,7 @@ sna_dri_copy_to_front(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		get_drawable_deltas(draw, pixmap, &dx, &dy);
 	}
 
-	if (sna->kgem.gen >= 60) {
-		/* Sandybridge introduced a separate ring which it uses to
-		 * perform blits. Switching rendering between rings incurs
-		 * a stall as we wait upon the old ring to finish and
-		 * flush its render cache before we can proceed on with
-		 * the operation on the new ring.
-		 *
-		 * As this buffer, we presume, has just been written to by
-		 * the DRI client using the RENDER ring, we want to perform
-		 * our operation on the same ring, and ideally on the same
-		 * ring as we will flip from (which should be the RENDER ring
-		 * as well).
-		 */
-		kgem_set_mode(&sna->kgem, KGEM_RENDER);
-	}
+	sna_dri_select_mode(sna, src_bo, flush);
 
 	damage(pixmap, region);
 	if (region) {
@@ -602,8 +635,7 @@ sna_dri_copy_from_front(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		get_drawable_deltas(draw, pixmap, &dx, &dy);
 	}
 
-	if (sna->kgem.gen >= 60)
-		kgem_set_mode(&sna->kgem, KGEM_RENDER);
+	sna_dri_select_mode(sna, src_bo, false);
 
 	if (region) {
 		boxes = REGION_RECTS(region);
@@ -656,21 +688,7 @@ sna_dri_copy(struct sna *sna, DrawablePtr draw, RegionPtr region,
 		n = 1;
 	}
 
-	if (sna->kgem.gen >= 60) {
-		/* Sandybridge introduced a separate ring which it uses to
-		 * perform blits. Switching rendering between rings incurs
-		 * a stall as we wait upon the old ring to finish and
-		 * flush its render cache before we can proceed on with
-		 * the operation on the new ring.
-		 *
-		 * As this buffer, we presume, has just been written to by
-		 * the DRI client using the RENDER ring, we want to perform
-		 * our operation on the same ring, and ideally on the same
-		 * ring as we will flip from (which should be the RENDER ring
-		 * as well).
-		 */
-		kgem_set_mode(&sna->kgem, KGEM_RENDER);
-	}
+	sna_dri_select_mode(sna, src_bo, false);
 
 	sna->render.copy_boxes(sna, GXcopy,
 			       (PixmapPtr)draw, src_bo, 0, 0,


More information about the xorg-commit mailing list