xf86-video-intel: 3 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_composite.c src/sna/sna_display.c src/sna/sna_glyphs.c src/sna/sna.h src/sna/sna_render.c src/sna/sna_render.h src/sna/sna_render_inline.h src/sna/sna_trapezoids.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Feb 8 03:55:14 PST 2013


 src/sna/gen2_render.c       |    4 -
 src/sna/gen3_render.c       |   15 ++--
 src/sna/gen4_render.c       |   50 ++++++---------
 src/sna/gen5_render.c       |   43 ++++++-------
 src/sna/gen6_render.c       |   28 ++++++--
 src/sna/gen7_render.c       |   28 ++++++--
 src/sna/kgem.c              |    2 
 src/sna/sna.h               |    3 
 src/sna/sna_accel.c         |   23 +++----
 src/sna/sna_composite.c     |    2 
 src/sna/sna_display.c       |    3 
 src/sna/sna_glyphs.c        |   19 ++++--
 src/sna/sna_render.c        |   15 ++--
 src/sna/sna_render.h        |    5 +
 src/sna/sna_render_inline.h |   18 ++++-
 src/sna/sna_trapezoids.c    |  139 +++++++++++++++++++++++++-------------------
 16 files changed, 228 insertions(+), 169 deletions(-)

New commits:
commit ae5399aaf9ef57d33e8fd957e8a96964897c09b3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 8 11:31:21 2013 +0000

    sna: Force the fallback path for unaccelerated randr damage
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_display.c b/src/sna/sna_display.c
index 748417d..b24bad5 100644
--- a/src/sna/sna_display.c
+++ b/src/sna/sna_display.c
@@ -3264,7 +3264,8 @@ void sna_mode_redisplay(struct sna *sna)
 	if (RegionNil(region))
 		return;
 
-	if (!sna_pixmap_move_to_gpu(sna->front, MOVE_READ)) {
+	if (!can_render(sna) ||
+	    !sna_pixmap_move_to_gpu(sna->front, MOVE_READ)) {
 		if (!sna_pixmap_move_to_cpu(sna->front, MOVE_READ))
 			return;
 
commit c69b4389abc324533a9a311c17a667bf8a1e1673
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Feb 7 22:54:37 2013 +0000

    sna/gen4: Split the have_render flag in separate prefer_gpu hints
    
    The idea is to implement more fine-grained checks as we may want
    different heuristics for desktops with GT1s than for mobile GT2s, etc.
    
    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 b539e27..4d92adc 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -2227,7 +2227,7 @@ gen2_check_composite_spans(struct sna *sna,
 		return false;
 
 	if (need_tiling(sna, width, height)) {
-		if (!is_gpu(dst->pDrawable)) {
+		if (!is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
 			DBG(("%s: fallback, tiled operation not on GPU\n",
 			     __FUNCTION__));
 			return false;
@@ -3143,10 +3143,12 @@ bool gen2_render_init(struct sna *sna)
 	 */
 #if !NO_COMPOSITE
 	render->composite = gen2_render_composite;
+	render->prefer_gpu |= PREFER_GPU_RENDER;
 #endif
 #if !NO_COMPOSITE_SPANS
 	render->check_composite_spans = gen2_check_composite_spans;
 	render->composite_spans = gen2_render_composite_spans;
+	render->prefer_gpu |= PREFER_GPU_SPANS;
 #endif
 	render->fill_boxes = gen2_render_fill_boxes;
 	render->fill = gen2_render_fill;
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 6b9a2f8..95d44ab 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2658,7 +2658,7 @@ source_use_blt(struct sna *sna, PicturePtr picture)
 	if (too_large(picture->pDrawable->width, picture->pDrawable->height))
 		return true;
 
-	return !is_gpu(picture->pDrawable);
+	return !is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER);
 }
 
 static bool
@@ -3884,12 +3884,11 @@ gen3_check_composite_spans(struct sna *sna,
 	if (gen3_composite_fallback(sna, op, src, NULL, dst))
 		return false;
 
-	if (need_tiling(sna, width, height)) {
-		if (!is_gpu(dst->pDrawable)) {
-			DBG(("%s: fallback, tiled operation not on GPU\n",
-			     __FUNCTION__));
-			return false;
-		}
+	if (need_tiling(sna, width, height) &&
+	    !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
+		DBG(("%s: fallback, tiled operation not on GPU\n",
+		     __FUNCTION__));
+		return false;
 	}
 
 	return true;
@@ -5205,10 +5204,12 @@ bool gen3_render_init(struct sna *sna)
 
 #if !NO_COMPOSITE
 	render->composite = gen3_render_composite;
+	render->prefer_gpu |= PREFER_GPU_RENDER;
 #endif
 #if !NO_COMPOSITE_SPANS
 	render->check_composite_spans = gen3_check_composite_spans;
 	render->composite_spans = gen3_render_composite_spans;
+	render->prefer_gpu |= PREFER_GPU_SPANS;
 #endif
 
 	render->video = gen3_render_video;
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index cc1778a..53fe52a 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1580,15 +1580,6 @@ gen4_composite_set_target(struct sna *sna,
 	return true;
 }
 
-static inline bool
-picture_is_cpu(PicturePtr picture)
-{
-	if (!picture->pDrawable)
-		return false;
-
-	return !is_gpu(picture->pDrawable);
-}
-
 static bool
 try_blt(struct sna *sna,
 	PicturePtr dst, PicturePtr src,
@@ -1613,7 +1604,7 @@ try_blt(struct sna *sna,
 		return true;
 
 	/* is the source picture only in cpu memory e.g. a shm pixmap? */
-	return picture_is_cpu(src);
+	return picture_is_cpu(sna, src);
 }
 
 static bool
@@ -1635,9 +1626,10 @@ has_alphamap(PicturePtr p)
 }
 
 static bool
-need_upload(PicturePtr p)
+need_upload(struct sna *sna, PicturePtr p)
 {
-	return p->pDrawable && untransformed(p) && !is_gpu(p->pDrawable);
+	return p->pDrawable && untransformed(p) &&
+		!is_gpu(sna, p->pDrawable, PREFER_GPU_RENDER);
 }
 
 static bool
@@ -1660,7 +1652,7 @@ source_is_busy(PixmapPtr pixmap)
 }
 
 static bool
-source_fallback(PicturePtr p, PixmapPtr pixmap)
+source_fallback(struct sna *sna, PicturePtr p, PixmapPtr pixmap)
 {
 	if (sna_picture_is_solid(p, NULL))
 		return false;
@@ -1675,7 +1667,7 @@ source_fallback(PicturePtr p, PixmapPtr pixmap)
 	if (pixmap && source_is_busy(pixmap))
 		return false;
 
-	return has_alphamap(p) || !gen4_check_filter(p) || need_upload(p);
+	return has_alphamap(p) || !gen4_check_filter(p) || need_upload(sna, p);
 }
 
 static bool
@@ -1698,11 +1690,11 @@ gen4_composite_fallback(struct sna *sna,
 	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
 
 	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
-	src_fallback = source_fallback(src, src_pixmap);
+	src_fallback = source_fallback(sna, src, src_pixmap);
 
 	if (mask) {
 		mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL;
-		mask_fallback = source_fallback(mask, mask_pixmap);
+		mask_fallback = source_fallback(sna, mask, mask_pixmap);
 	} else {
 		mask_pixmap = NULL;
 		mask_fallback = false;
@@ -2098,7 +2090,8 @@ gen4_check_composite_spans(struct sna *sna,
 		return false;
 	}
 
-	if (need_tiling(sna, width, height) && !is_gpu(dst->pDrawable)) {
+	if (need_tiling(sna, width, height) &&
+	    !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
 		DBG(("%s: fallback, tiled operation not on GPU\n",
 		     __FUNCTION__));
 		return false;
@@ -2108,24 +2101,20 @@ gen4_check_composite_spans(struct sna *sna,
 		return FORCE_SPANS > 0;
 
 	if ((flags & COMPOSITE_SPANS_RECTILINEAR) == 0) {
-		struct sna_pixmap *priv;
-
-		if (FORCE_NONRECTILINEAR_SPANS)
-			return FORCE_NONRECTILINEAR_SPANS > 0;
-
-		priv = sna_pixmap_from_drawable(dst->pDrawable);
+		struct sna_pixmap *priv = sna_pixmap_from_drawable(dst->pDrawable);
 		assert(priv);
 
 		if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
 			return true;
 
-		if ((flags & COMPOSITE_SPANS_INPLACE_HINT) == 0 &&
-		    priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
-			return true;
+		if (flags & COMPOSITE_SPANS_INPLACE_HINT)
+			return false;
 
-		DBG(("%s: fallback, non-rectilinear spans to idle bo\n",
-		     __FUNCTION__));
-		return false;
+		if ((sna->render.prefer_gpu & PREFER_GPU_SPANS) == 0 &&
+		    dst->format == PICT_a8)
+			return false;
+
+		return priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo);
 	}
 
 	return true;
@@ -3124,10 +3113,13 @@ bool gen4_render_init(struct sna *sna)
 
 #if !NO_COMPOSITE
 	sna->render.composite = gen4_render_composite;
+	sna->render.prefer_gpu |= PREFER_GPU_RENDER;
 #endif
 #if !NO_COMPOSITE_SPANS
 	sna->render.check_composite_spans = gen4_check_composite_spans;
 	sna->render.composite_spans = gen4_render_composite_spans;
+	if (0)
+		sna->render.prefer_gpu |= PREFER_GPU_SPANS;
 #endif
 
 #if !NO_VIDEO
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 35f70f8..6e11996 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1556,15 +1556,6 @@ gen5_composite_set_target(struct sna *sna,
 	return true;
 }
 
-static inline bool
-picture_is_cpu(PicturePtr picture)
-{
-	if (!picture->pDrawable)
-		return false;
-
-	return !is_gpu(picture->pDrawable);
-}
-
 static bool
 try_blt(struct sna *sna,
 	PicturePtr dst, PicturePtr src,
@@ -1589,7 +1580,7 @@ try_blt(struct sna *sna,
 		return true;
 
 	/* is the source picture only in cpu memory e.g. a shm pixmap? */
-	return picture_is_cpu(src);
+	return picture_is_cpu(sna, src);
 }
 
 static bool
@@ -1614,9 +1605,10 @@ has_alphamap(PicturePtr p)
 }
 
 static bool
-need_upload(PicturePtr p)
+need_upload(struct sna *sna, PicturePtr p)
 {
-	return p->pDrawable && untransformed(p) && !is_gpu(p->pDrawable);
+	return p->pDrawable && untransformed(p) &&
+		!is_gpu(sna, p->pDrawable, PREFER_GPU_RENDER);
 }
 
 static bool
@@ -1639,7 +1631,7 @@ source_is_busy(PixmapPtr pixmap)
 }
 
 static bool
-source_fallback(PicturePtr p, PixmapPtr pixmap)
+source_fallback(struct sna *sna, PicturePtr p, PixmapPtr pixmap)
 {
 	if (sna_picture_is_solid(p, NULL))
 		return false;
@@ -1652,7 +1644,7 @@ source_fallback(PicturePtr p, PixmapPtr pixmap)
 	if (pixmap && source_is_busy(pixmap))
 		return false;
 
-	return has_alphamap(p) || !gen5_check_filter(p) || need_upload(p);
+	return has_alphamap(p) || !gen5_check_filter(p) || need_upload(sna, p);
 }
 
 static bool
@@ -1675,11 +1667,11 @@ gen5_composite_fallback(struct sna *sna,
 	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
 
 	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
-	src_fallback = source_fallback(src, src_pixmap);
+	src_fallback = source_fallback(sna, src, src_pixmap);
 
 	if (mask) {
 		mask_pixmap = mask->pDrawable ? get_drawable_pixmap(mask->pDrawable) : NULL;
-		mask_fallback = source_fallback(mask, mask_pixmap);
+		mask_fallback = source_fallback(sna, mask, mask_pixmap);
 	} else {
 		mask_pixmap = NULL;
 		mask_fallback = false;
@@ -2075,7 +2067,8 @@ gen5_check_composite_spans(struct sna *sna,
 		return false;
 	}
 
-	if (need_tiling(sna, width, height) && !is_gpu(dst->pDrawable)) {
+	if (need_tiling(sna, width, height) &&
+	    !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
 		DBG(("%s: fallback, tiled operation not on GPU\n",
 		     __FUNCTION__));
 		return false;
@@ -2088,13 +2081,14 @@ gen5_check_composite_spans(struct sna *sna,
 		if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
 			return true;
 
-		if ((flags & COMPOSITE_SPANS_INPLACE_HINT) == 0 &&
-		    priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
-			return true;
+		if (flags & COMPOSITE_SPANS_INPLACE_HINT)
+			return false;
 
-		DBG(("%s: fallback, non-rectilinear spans to idle bo\n",
-		     __FUNCTION__));
-		return false;
+		if ((sna->render.prefer_gpu & PREFER_GPU_SPANS) == 0 &&
+		    dst->format == PICT_a8)
+			return false;
+
+		return priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo);
 	}
 
 	return true;
@@ -3272,10 +3266,13 @@ bool gen5_render_init(struct sna *sna)
 
 #if !NO_COMPOSITE
 	sna->render.composite = gen5_render_composite;
+	sna->render.prefer_gpu |= PREFER_GPU_RENDER;
 #endif
 #if !NO_COMPOSITE_SPANS
 	sna->render.check_composite_spans = gen5_check_composite_spans;
 	sna->render.composite_spans = gen5_render_composite_spans;
+	if (DEVICE_ID(sna->PciInfo) == 0x0044)
+		sna->render.prefer_gpu |= PREFER_GPU_SPANS;
 #endif
 	sna->render.video = gen5_render_video;
 
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index ec64250..76d0c8c 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2422,7 +2422,8 @@ gen6_check_composite_spans(struct sna *sna,
 		return false;
 	}
 
-	if (need_tiling(sna, width, height) && !is_gpu(dst->pDrawable)) {
+	if (need_tiling(sna, width, height) &&
+	    !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
 		DBG(("%s: fallback, tiled operation not on GPU\n",
 		     __FUNCTION__));
 		return false;
@@ -2435,13 +2436,10 @@ gen6_check_composite_spans(struct sna *sna,
 		if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
 			return true;
 
-		if ((flags & COMPOSITE_SPANS_INPLACE_HINT) == 0 &&
-		    priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo))
-			return true;
+		if (flags & COMPOSITE_SPANS_INPLACE_HINT)
+			return false;
 
-		DBG(("%s: fallback, non-rectilinear spans to idle bo\n",
-		     __FUNCTION__));
-		return false;
+		return priv->gpu_bo && kgem_bo_is_busy(priv->gpu_bo);
 	}
 
 	return true;
@@ -3557,6 +3555,16 @@ static void gen6_render_fini(struct sna *sna)
 	kgem_bo_destroy(&sna->kgem, sna->render_state.gen6.general_bo);
 }
 
+static bool is_gt2(struct sna *sna)
+{
+	return DEVICE_ID(sna->PciInfo) & 0x20;
+}
+
+static bool is_mobile(struct sna *sna)
+{
+	return (DEVICE_ID(sna->PciInfo) & 0xf) == 0x6;
+}
+
 static bool gen6_render_setup(struct sna *sna)
 {
 	struct gen6_render_state *state = &sna->render_state.gen6;
@@ -3565,7 +3573,7 @@ static bool gen6_render_setup(struct sna *sna)
 	int i, j, k, l, m;
 
 	state->info = &gt1_info;
-	if (DEVICE_ID(sna->PciInfo) & 0x20)
+	if (is_gt2(sna))
 		state->info = &gt2_info; /* XXX requires GT_MODE WiZ disabled */
 
 	sna_static_stream_init(&general);
@@ -3646,10 +3654,14 @@ bool gen6_render_init(struct sna *sna)
 
 #if !NO_COMPOSITE
 	sna->render.composite = gen6_render_composite;
+	sna->render.prefer_gpu |= PREFER_GPU_RENDER;
+
 #endif
 #if !NO_COMPOSITE_SPANS
 	sna->render.check_composite_spans = gen6_check_composite_spans;
 	sna->render.composite_spans = gen6_render_composite_spans;
+	if (is_mobile(sna))
+		sna->render.prefer_gpu |= PREFER_GPU_SPANS;
 #endif
 	sna->render.video = gen6_render_video;
 
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 59b38f6..f05d6f9 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2553,12 +2553,11 @@ gen7_check_composite_spans(struct sna *sna,
 	if (gen7_composite_fallback(sna, src, NULL, dst))
 		return false;
 
-	if (need_tiling(sna, width, height)) {
-		if (!is_gpu(dst->pDrawable)) {
-			DBG(("%s: fallback, tiled operation not on GPU\n",
-			     __FUNCTION__));
-			return false;
-		}
+	if (need_tiling(sna, width, height) &&
+	    !is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
+		DBG(("%s: fallback, tiled operation not on GPU\n",
+		     __FUNCTION__));
+		return false;
 	}
 
 	return true;
@@ -3647,6 +3646,16 @@ static void gen7_render_fini(struct sna *sna)
 	kgem_bo_destroy(&sna->kgem, sna->render_state.gen7.general_bo);
 }
 
+static bool is_gt2(struct sna *sna)
+{
+	return DEVICE_ID(sna->PciInfo) & 0x20;
+}
+
+static bool is_mobile(struct sna *sna)
+{
+	return (DEVICE_ID(sna->PciInfo) & 0xf) == 0x6;
+}
+
 static bool gen7_render_setup(struct sna *sna)
 {
 	struct gen7_render_state *state = &sna->render_state.gen7;
@@ -3658,14 +3667,14 @@ static bool gen7_render_setup(struct sna *sna)
 		state->info = &ivb_gt_info;
 		if (DEVICE_ID(sna->PciInfo) & 0xf) {
 			state->info = &ivb_gt1_info;
-			if (DEVICE_ID(sna->PciInfo) & 0x20)
+			if (is_gt2(sna))
 				state->info = &ivb_gt2_info; /* XXX requires GT_MODE WiZ disabled */
 		}
 	} else if (sna->kgem.gen == 075) {
 		state->info = &hsw_gt_info;
 		if (DEVICE_ID(sna->PciInfo) & 0xf) {
 			state->info = &hsw_gt1_info;
-			if (DEVICE_ID(sna->PciInfo) & 0x20)
+			if (is_gt2(sna))
 				state->info = &hsw_gt2_info;
 		}
 	} else
@@ -3744,10 +3753,13 @@ bool gen7_render_init(struct sna *sna)
 
 #if !NO_COMPOSITE
 	sna->render.composite = gen7_render_composite;
+	sna->render.prefer_gpu |= PREFER_GPU_RENDER;
 #endif
 #if !NO_COMPOSITE_SPANS
 	sna->render.check_composite_spans = gen7_check_composite_spans;
 	sna->render.composite_spans = gen7_render_composite_spans;
+	if (is_mobile(sna))
+		sna->render.prefer_gpu |= PREFER_GPU_SPANS;
 #endif
 	sna->render.video = gen7_render_video;
 
diff --git a/src/sna/sna.h b/src/sna/sna.h
index e407359..5a57a6e 100644
--- a/src/sna/sna.h
+++ b/src/sna/sna.h
@@ -256,7 +256,6 @@ struct sna {
 		struct gen6_render_state gen6;
 		struct gen7_render_state gen7;
 	} render_state;
-	uint32_t have_render;
 
 	bool dri_available;
 	bool dri_open;
@@ -672,7 +671,7 @@ static inline bool wedged(struct sna *sna)
 
 static inline bool can_render(struct sna *sna)
 {
-	return likely(!sna->kgem.wedged && sna->have_render);
+	return likely(!sna->kgem.wedged && sna->render.prefer_gpu & PREFER_GPU_RENDER);
 }
 
 static inline uint32_t pixmap_size(PixmapPtr pixmap)
diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c
index 7c8a360..0edc1e8 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -879,7 +879,8 @@ sna_pixmap_create_scratch(ScreenPtr screen,
 	     width, height, depth, tiling));
 
 	bpp = bits_per_pixel(depth);
-	if (tiling == I915_TILING_Y && !sna->have_render)
+	if (tiling == I915_TILING_Y &&
+	    (sna->render.prefer_gpu & PREFER_GPU_RENDER) == 0)
 		tiling = I915_TILING_X;
 
 	if (tiling == I915_TILING_Y &&
@@ -1180,7 +1181,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 		goto fallback;
 	}
 
-	if (unlikely(!sna->have_render))
+	if (unlikely((sna->render.prefer_gpu & PREFER_GPU_RENDER) == 0))
 		flags &= ~KGEM_CAN_CREATE_GPU;
 	if (wedged(sna))
 		flags = 0;
@@ -14199,31 +14200,30 @@ bool sna_accel_init(ScreenPtr screen, struct sna *sna)
 		return false;
 
 	backend = "no";
-	sna->have_render = false;
 	no_render_init(sna);
 
 	if (sna_option_accel_blt(sna) || sna->info->gen >= 0100) {
 	} else if (sna->info->gen >= 070) {
-		if ((sna->have_render = gen7_render_init(sna)))
+		if (gen7_render_init(sna))
 			backend = "IvyBridge";
 	} else if (sna->info->gen >= 060) {
-		if ((sna->have_render = gen6_render_init(sna)))
+		if (gen6_render_init(sna))
 			backend = "SandyBridge";
 	} else if (sna->info->gen >= 050) {
-		if ((sna->have_render = gen5_render_init(sna)))
+		if (gen5_render_init(sna))
 			backend = "Ironlake";
 	} else if (sna->info->gen >= 040) {
-		if ((sna->have_render = gen4_render_init(sna)))
+		if (gen4_render_init(sna))
 			backend = "Broadwater/Crestline";
 	} else if (sna->info->gen >= 030) {
-		if ((sna->have_render = gen3_render_init(sna)))
+		if (gen3_render_init(sna))
 			backend = "gen3";
 	} else if (sna->info->gen >= 020) {
-		if ((sna->have_render = gen2_render_init(sna)))
+		if (gen2_render_init(sna))
 			backend = "gen2";
 	}
-	DBG(("%s(backend=%s, have_render=%d)\n",
-	     __FUNCTION__, backend, sna->have_render));
+	DBG(("%s(backend=%s, prefer_gpu=%x)\n",
+	     __FUNCTION__, backend, sna->render.prefer_gpu));
 
 	kgem_reset(&sna->kgem);
 
@@ -14252,7 +14252,6 @@ void sna_accel_create(struct sna *sna)
 fail:
 	xf86DrvMsg(sna->scrn->scrnIndex, X_ERROR,
 		   "Failed to allocate caches, disabling RENDER acceleration\n");
-	sna->have_render = false;
 	no_render_init(sna);
 }
 
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index e82d5f4..c329fb8 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -584,7 +584,7 @@ sna_composite(CARD8 op,
 	}
 
 	if (use_cpu(pixmap, priv, op, width, height) &&
-	    !picture_is_gpu(src) && !picture_is_gpu(mask)) {
+	    !picture_is_gpu(sna, src) && !picture_is_gpu(sna, mask)) {
 		DBG(("%s: fallback, dst pixmap=%ld is too small (or completely damaged)\n",
 		     __FUNCTION__, pixmap->drawable.serialNumber));
 		goto fallback;
diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c
index 130c1ea..ad050df 100644
--- a/src/sna/sna_glyphs.c
+++ b/src/sna/sna_glyphs.c
@@ -193,11 +193,17 @@ bool sna_glyphs_create(struct sna *sna)
 	if (sna->render.white_image == NULL)
 		goto bail;
 
-	if (!can_render(sna))
+	if (!can_render(sna)) {
+		DBG(("%s: no render acceleration, no render glyph caches\n",
+		     __FUNCTION__));
 		return true;
+	}
 
-	if (xf86IsEntityShared(sna->scrn->entityList[0]))
+	if (xf86IsEntityShared(sna->scrn->entityList[0])) {
+		DBG(("%s: shared GlyphPictures, no render glyph caches\n",
+		     __FUNCTION__));
 		return true;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(formats); i++) {
 		struct sna_glyph_cache *cache = &sna->render.glyph[i];
@@ -218,8 +224,11 @@ bool sna_glyphs_create(struct sna *sna)
 					      CACHE_PICTURE_SIZE,
 					      depth,
 					      SNA_CREATE_GLYPHS);
-		if (!pixmap)
+		if (!pixmap) {
+			DBG(("%s: failed to allocate pixmap for Glyph cache\n",
+			     __FUNCTION__));
 			goto bail;
+		}
 
 		priv = sna_pixmap(pixmap);
 		if (priv != NULL) {
@@ -1678,7 +1687,7 @@ sna_glyphs(CARD8 op,
 	}
 
 	if ((too_small(priv) || DAMAGE_IS_ALL(priv->cpu_damage)) &&
-	    !picture_is_gpu(src)) {
+	    !picture_is_gpu(sna, src)) {
 		DBG(("%s: fallback -- too small (%dx%d)\n",
 		     __FUNCTION__, dst->pDrawable->width, dst->pDrawable->height));
 		goto fallback;
@@ -2002,7 +2011,7 @@ sna_glyphs__shared(CARD8 op,
 	}
 
 	if ((too_small(priv) || DAMAGE_IS_ALL(priv->cpu_damage)) &&
-	    !picture_is_gpu(src)) {
+	    !picture_is_gpu(sna, src)) {
 		DBG(("%s: fallback -- too small (%dx%d)\n",
 		     __FUNCTION__, dst->pDrawable->width, dst->pDrawable->height));
 		goto fallback;
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 7784a5b..6c5d962 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -87,8 +87,8 @@ no_render_composite(struct sna *sna,
 	if (mask)
 		return false;
 
-	if (!is_gpu(dst->pDrawable) &&
-	    (src->pDrawable == NULL || !is_gpu(src->pDrawable)))
+	if (!is_gpu(sna, dst->pDrawable, PREFER_GPU_BLT) &&
+	    (src->pDrawable == NULL || !is_gpu(sna, src->pDrawable, PREFER_GPU_BLT)))
 		return false;
 
 	return sna_blt_composite(sna,
@@ -279,7 +279,9 @@ void no_render_init(struct sna *sna)
 {
 	struct sna_render *render = &sna->render;
 
-	memset (render,0, sizeof (*render));
+	memset (render, 0, sizeof (*render));
+
+	render->prefer_gpu = PREFER_GPU_BLT;
 
 	render->vertices = render->vertex_data;
 	render->vertex_size = ARRAY_SIZE(render->vertex_data);
@@ -1533,7 +1535,8 @@ sna_render_picture_fixup(struct sna *sna,
 
 	if (picture->alphaMap) {
 		DBG(("%s: alphamap\n", __FUNCTION__));
-		if (is_gpu(picture->pDrawable) || is_gpu(picture->alphaMap->pDrawable)) {
+		if (is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER) ||
+		    is_gpu(sna, picture->alphaMap->pDrawable, PREFER_GPU_RENDER)) {
 			return sna_render_picture_flatten(sna, picture, channel,
 							  x, y, w, h, dst_x, dst_y);
 		}
@@ -1543,7 +1546,7 @@ sna_render_picture_fixup(struct sna *sna,
 
 	if (picture->filter == PictFilterConvolution) {
 		DBG(("%s: convolution\n", __FUNCTION__));
-		if (is_gpu(picture->pDrawable)) {
+		if (is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER)) {
 			return sna_render_picture_convolve(sna, picture, channel,
 							   x, y, w, h, dst_x, dst_y);
 		}
@@ -1704,7 +1707,7 @@ sna_render_picture_convert(struct sna *sna,
 		return 0;
 	}
 
-	if (fixup_alpha && is_gpu(&pixmap->drawable)) {
+	if (fixup_alpha && is_gpu(sna, &pixmap->drawable, PREFER_GPU_RENDER)) {
 		ScreenPtr screen = pixmap->drawable.pScreen;
 		PixmapPtr tmp;
 		PicturePtr src, dst;
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index a8084f2..01176c6 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -215,6 +215,11 @@ struct sna_render {
 	int max_3d_size;
 	int max_3d_pitch;
 
+	unsigned prefer_gpu;
+#define PREFER_GPU_BLT 0x1
+#define PREFER_GPU_RENDER 0x2
+#define PREFER_GPU_SPANS 0x4
+
 	bool (*composite)(struct sna *sna, uint8_t op,
 			  PicturePtr dst, PicturePtr src, PicturePtr mask,
 			  int16_t src_x, int16_t src_y,
diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index 432201f..7d9f2ca 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -67,7 +67,7 @@ static inline void batch_emit_float(struct sna *sna, float f)
 }
 
 static inline bool
-is_gpu(DrawablePtr drawable)
+is_gpu(struct sna *sna, DrawablePtr drawable, unsigned prefer)
 {
 	struct sna_pixmap *priv = sna_pixmap_from_drawable(drawable);
 
@@ -77,7 +77,8 @@ is_gpu(DrawablePtr drawable)
 	if (priv->cpu_damage == NULL)
 		return true;
 
-	if (priv->gpu_damage && !priv->gpu_bo->proxy)
+	if (priv->gpu_damage && !priv->gpu_bo->proxy &&
+	    (sna->render.prefer_gpu & prefer))
 		return true;
 
 	if (priv->cpu_bo && kgem_bo_is_busy(priv->cpu_bo))
@@ -108,11 +109,20 @@ unattached(DrawablePtr drawable)
 }
 
 static inline bool
-picture_is_gpu(PicturePtr picture)
+picture_is_gpu(struct sna *sna, PicturePtr picture)
 {
 	if (!picture || !picture->pDrawable)
 		return false;
-	return is_gpu(picture->pDrawable);
+	return is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER);
+}
+
+static inline bool
+picture_is_cpu(struct sna *sna, PicturePtr picture)
+{
+	if (!picture->pDrawable)
+		return false;
+
+	return !is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER);
 }
 
 static inline bool sna_blt_compare_depth(DrawablePtr src, DrawablePtr dst)
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 547e4f5..406a6b3 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -2457,7 +2457,8 @@ is_mono(PicturePtr dst, PictFormatPtr mask)
 }
 
 static bool
-trapezoids_inplace_fallback(CARD8 op,
+trapezoids_inplace_fallback(struct sna *sna,
+			    CARD8 op,
 			    PicturePtr src, PicturePtr dst, PictFormatPtr mask,
 			    int ntrap, xTrapezoid *traps)
 {
@@ -2497,7 +2498,7 @@ trapezoids_inplace_fallback(CARD8 op,
 		return false;
 	}
 
-	if (is_gpu(dst->pDrawable)) {
+	if (is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
 		DBG(("%s: not performing inplace as dst is already on the GPU\n",
 		     __FUNCTION__));
 		return false;
@@ -2581,7 +2582,8 @@ static void rasterize_traps_thread(void *arg)
 }
 
 static void
-trapezoids_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
+trapezoids_fallback(struct sna *sna,
+		    CARD8 op, PicturePtr src, PicturePtr dst,
 		    PictFormatPtr maskFormat, INT16 xSrc, INT16 ySrc,
 		    int ntrap, xTrapezoid * traps)
 {
@@ -2636,7 +2638,8 @@ trapezoids_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
 
 		DBG(("%s: mask (%dx%d) depth=%d, format=%08x\n",
 		     __FUNCTION__, width, height, depth, format));
-		if (is_gpu(dst->pDrawable) || picture_is_gpu(src)) {
+		if (is_gpu(sna, dst->pDrawable, PREFER_GPU_RENDER) ||
+		    picture_is_gpu(sna, src)) {
 			int num_threads;
 
 			scratch = sna_pixmap_create_upload(screen,
@@ -2760,7 +2763,7 @@ trapezoids_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
 			maskFormat = PictureMatchFormat(screen, 8, PICT_a8);
 
 		for (; ntrap; ntrap--, traps++)
-			trapezoids_fallback(op,
+			trapezoids_fallback(sna, op,
 					    src, dst, maskFormat,
 					    xSrc, ySrc, 1, traps);
 	}
@@ -3420,7 +3423,8 @@ pixsolid_unaligned_box_row(struct pixman_inplace *pi,
 }
 
 static bool
-composite_unaligned_boxes_inplace__solid(CARD8 op, uint32_t color,
+composite_unaligned_boxes_inplace__solid(struct sna *sna,
+					 CARD8 op, uint32_t color,
 					 PicturePtr dst, int n, xTrapezoid *t,
 					 bool force_fallback)
 {
@@ -3428,9 +3432,9 @@ composite_unaligned_boxes_inplace__solid(CARD8 op, uint32_t color,
 	int16_t dx, dy;
 
 	DBG(("%s: force=%d, is_gpu=%d, op=%d, color=%x\n", __FUNCTION__,
-	     force_fallback, is_gpu(dst->pDrawable), op, color));
+	     force_fallback, is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS), op, color));
 
-	if (!force_fallback && is_gpu(dst->pDrawable)) {
+	if (!force_fallback && is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
 		DBG(("%s: fallback -- can not perform operation in place, destination busy\n",
 		     __FUNCTION__));
 
@@ -3744,13 +3748,15 @@ static void rectilinear_inplace_thread(void *arg)
 }
 
 static bool
-composite_unaligned_boxes_inplace(CARD8 op,
+composite_unaligned_boxes_inplace(struct sna *sna,
+				  CARD8 op,
 				  PicturePtr src, int16_t src_x, int16_t src_y,
 				  PicturePtr dst, int n, xTrapezoid *t,
 				  bool force_fallback)
 {
 	if (!force_fallback &&
-	    (is_gpu(dst->pDrawable) || picture_is_gpu(src))) {
+	    (is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS) ||
+	     picture_is_gpu(sna, src))) {
 		DBG(("%s: fallback -- not forcing\n", __FUNCTION__));
 		return false;
 	}
@@ -3894,7 +3900,8 @@ composite_unaligned_boxes_inplace(CARD8 op,
 }
 
 static bool
-composite_unaligned_boxes_fallback(CARD8 op,
+composite_unaligned_boxes_fallback(struct sna *sna,
+				   CARD8 op,
 				   PicturePtr src,
 				   PicturePtr dst,
 				   INT16 src_x, INT16 src_y,
@@ -3908,12 +3915,12 @@ composite_unaligned_boxes_fallback(CARD8 op,
 	int n;
 
 	if (sna_picture_is_solid(src, &color) &&
-	    composite_unaligned_boxes_inplace__solid(op, color, dst,
+	    composite_unaligned_boxes_inplace__solid(sna, op, color, dst,
 						     ntrap, traps,
 						     force_fallback))
 		return true;
 
-	if (composite_unaligned_boxes_inplace(op, src, src_x, src_y,
+	if (composite_unaligned_boxes_inplace(sna, op, src, src_x, src_y,
 					      dst, ntrap, traps,
 					      force_fallback))
 		return true;
@@ -4037,7 +4044,7 @@ composite_unaligned_boxes(struct sna *sna,
 	    !sna->render.check_composite_spans(sna, op, src, dst, 0, 0,
 					       COMPOSITE_SPANS_RECTILINEAR)) {
 fallback:
-		return composite_unaligned_boxes_fallback(op, src, dst,
+		return composite_unaligned_boxes_fallback(sna, op, src, dst,
 							  src_x, src_y,
 							  ntrap, traps,
 							  force_fallback);
@@ -4285,7 +4292,8 @@ mono_span_thread(void *arg)
 }
 
 static bool
-mono_trapezoids_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
+mono_trapezoids_span_converter(struct sna *sna,
+			       CARD8 op, PicturePtr src, PicturePtr dst,
 			       INT16 src_x, INT16 src_y,
 			       int ntrap, xTrapezoid *traps)
 {
@@ -4336,7 +4344,7 @@ mono_trapezoids_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 	unbounded = (!sna_drawable_is_clear(dst->pDrawable) &&
 		     !operator_is_bounded(op));
 
-	mono.sna = to_sna_from_drawable(dst->pDrawable);
+	mono.sna = sna;
 	if (!mono.sna->render.composite(mono.sna, op, src, NULL, dst,
 				       src_x + mono.clip.extents.x1 - dst_x - dx,
 				       src_y + mono.clip.extents.y1 - dst_y - dy,
@@ -4620,12 +4628,12 @@ span_thread(void *arg)
 }
 
 static bool
-trapezoid_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
+trapezoid_span_converter(struct sna *sna,
+			 CARD8 op, PicturePtr src, PicturePtr dst,
 			 PictFormatPtr maskFormat, unsigned int flags,
 			 INT16 src_x, INT16 src_y,
 			 int ntrap, xTrapezoid *traps)
 {
-	struct sna *sna;
 	struct sna_composite_spans_op tmp;
 	BoxRec extents;
 	pixman_region16_t clip;
@@ -4638,7 +4646,7 @@ trapezoid_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 		return false;
 
 	if (is_mono(dst, maskFormat))
-		return mono_trapezoids_span_converter(op, src, dst,
+		return mono_trapezoids_span_converter(sna, op, src, dst,
 						      src_x, src_y,
 						      ntrap, traps);
 
@@ -4649,7 +4657,6 @@ trapezoid_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 		return false;
 	}
 
-	sna = to_sna_from_drawable(dst->pDrawable);
 	if (!sna->render.check_composite_spans(sna, op, src, dst, 0, 0, flags)) {
 		DBG(("%s: fallback -- composite spans not supported\n",
 		     __FUNCTION__));
@@ -5315,7 +5322,8 @@ mono_inplace_composite_boxes(struct sna *sna,
 }
 
 static bool
-trapezoid_spans_maybe_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
+trapezoid_spans_maybe_inplace(struct sna *sna,
+			      CARD8 op, PicturePtr src, PicturePtr dst,
 			      PictFormatPtr maskFormat)
 {
 	struct sna_pixmap *priv;
@@ -5348,7 +5356,7 @@ trapezoid_spans_maybe_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
 
 	case PICT_x8r8g8b8:
 	case PICT_a8r8g8b8:
-		if (picture_is_gpu(src))
+		if (picture_is_gpu(sna, src))
 			return false;
 
 		switch (op) {
@@ -5395,7 +5403,8 @@ out:
 }
 
 static bool
-trapezoid_span_mono_inplace(CARD8 op,
+trapezoid_span_mono_inplace(struct sna *sna,
+			    CARD8 op,
 			    PicturePtr src,
 			    PicturePtr dst,
 			    INT16 src_x, INT16 src_y,
@@ -5441,7 +5450,7 @@ trapezoid_span_mono_inplace(CARD8 op,
 					     MOVE_WRITE | MOVE_READ))
 		return true;
 
-	mono.sna = to_sna_from_drawable(dst->pDrawable);
+	mono.sna = sna;
 	if (!mono_init(&mono, 2*ntrap))
 		return false;
 
@@ -6052,7 +6061,8 @@ static void inplace_thread(void *arg)
 }
 
 static bool
-trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
+trapezoid_span_inplace(struct sna *sna,
+		       CARD8 op, PicturePtr src, PicturePtr dst,
 		       PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
 		       int ntrap, xTrapezoid *traps,
 		       bool fallback)
@@ -6082,7 +6092,7 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
 		return false;
 	}
 
-	if (!fallback && is_gpu(dst->pDrawable)) {
+	if (!fallback && is_gpu(sna, dst->pDrawable, PREFER_GPU_SPANS)) {
 		DBG(("%s: fallback -- can not perform operation in place, destination busy\n",
 		     __FUNCTION__));
 
@@ -6090,7 +6100,7 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
 	}
 
 	if (is_mono(dst, maskFormat))
-		return trapezoid_span_mono_inplace(op, src, dst,
+		return trapezoid_span_mono_inplace(sna, op, src, dst,
 						   src_x, src_y, ntrap, traps);
 
 	if (dst->format == PICT_a8r8g8b8 || dst->format == PICT_x8r8g8b8)
@@ -6165,7 +6175,7 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
 		     __FUNCTION__));
 		do {
 			/* XXX unwind errors? */
-			if (!trapezoid_span_inplace(op, src, dst, NULL,
+			if (!trapezoid_span_inplace(sna, op, src, dst, NULL,
 						    src_x, src_y, 1, traps++,
 						    fallback))
 				return false;
@@ -6476,14 +6486,14 @@ sna_composite_trapezoids(CARD8 op,
 
 	force_fallback = FORCE_FALLBACK > 0;
 	if ((too_small(priv) || DAMAGE_IS_ALL(priv->cpu_damage)) &&
-	    !picture_is_gpu(src) && untransformed(src)) {
+	    !picture_is_gpu(sna, src) && untransformed(src)) {
 		DBG(("%s: force fallbacks --too small, %dx%d? %d, all-cpu? %d, src-is-cpu? %d\n",
 		     __FUNCTION__,
 		     dst->pDrawable->width,
 		     dst->pDrawable->height,
 		     too_small(priv),
 		     (int)DAMAGE_IS_ALL(priv->cpu_damage),
-		     !picture_is_gpu(src)));
+		     !picture_is_gpu(sna, src)));
 		force_fallback = true;
 	}
 	if (FORCE_FALLBACK < 0)
@@ -6550,24 +6560,24 @@ sna_composite_trapezoids(CARD8 op,
 		goto fallback;
 
 	if (is_mono(dst, maskFormat) &&
-	    mono_trapezoids_span_converter(op, src, dst,
+	    mono_trapezoids_span_converter(sna, op, src, dst,
 					   xSrc, ySrc,
 					   ntrap, traps))
 		return;
 
-	if (trapezoid_spans_maybe_inplace(op, src, dst, maskFormat)) {
+	if (trapezoid_spans_maybe_inplace(sna, op, src, dst, maskFormat)) {
 		flags |= COMPOSITE_SPANS_INPLACE_HINT;
-		if (trapezoid_span_inplace(op, src, dst, maskFormat,
+		if (trapezoid_span_inplace(sna, op, src, dst, maskFormat,
 					   xSrc, ySrc, ntrap, traps,
 					   false))
 			return;
 	}
 
-	if (trapezoid_span_converter(op, src, dst, maskFormat, flags,
+	if (trapezoid_span_converter(sna, op, src, dst, maskFormat, flags,
 				     xSrc, ySrc, ntrap, traps))
 		return;
 
-	if (trapezoid_span_inplace(op, src, dst, maskFormat,
+	if (trapezoid_span_inplace(sna, op, src, dst, maskFormat,
 				   xSrc, ySrc, ntrap, traps,
 				   false))
 		return;
@@ -6577,7 +6587,7 @@ sna_composite_trapezoids(CARD8 op,
 		return;
 
 fallback:
-	if (trapezoid_span_inplace(op, src, dst, maskFormat,
+	if (trapezoid_span_inplace(sna, op, src, dst, maskFormat,
 				   xSrc, ySrc, ntrap, traps,
 				   true))
 		return;
@@ -6586,12 +6596,13 @@ fallback:
 				    xSrc, ySrc, ntrap, traps))
 		return;
 
-	if (trapezoids_inplace_fallback(op, src, dst, maskFormat, ntrap, traps))
+	if (trapezoids_inplace_fallback(sna, op, src, dst, maskFormat,
+					ntrap, traps))
 		return;
 
 	DBG(("%s: fallback mask=%08x, ntrap=%d\n", __FUNCTION__,
 	     maskFormat ? (unsigned)maskFormat->format : 0, ntrap));
-	trapezoids_fallback(op, src, dst, maskFormat,
+	trapezoids_fallback(sna, op, src, dst, maskFormat,
 			    xSrc, ySrc,
 			    ntrap, traps);
 }
@@ -6613,7 +6624,8 @@ project_trap_onto_grid(const xTrap *in,
 }
 
 static bool
-mono_trap_span_converter(PicturePtr dst,
+mono_trap_span_converter(struct sna *sna,
+			 PicturePtr dst,
 			 INT16 x, INT16 y,
 			 int ntrap, xTrap *traps)
 {
@@ -6638,7 +6650,7 @@ mono_trap_span_converter(PicturePtr dst,
 	     mono.clip.extents.x2, mono.clip.extents.y2,
 	     x, y));
 
-	mono.sna = to_sna_from_drawable(dst->pDrawable);
+	mono.sna = sna;
 	if (!mono_init(&mono, 2*ntrap))
 		return false;
 
@@ -6683,11 +6695,11 @@ mono_trap_span_converter(PicturePtr dst,
 }
 
 static bool
-trap_span_converter(PicturePtr dst,
+trap_span_converter(struct sna *sna,
+		    PicturePtr dst,
 		    INT16 src_x, INT16 src_y,
 		    int ntrap, xTrap *trap)
 {
-	struct sna *sna;
 	struct sna_composite_spans_op tmp;
 	struct tor tor;
 	BoxRec extents;
@@ -6701,9 +6713,8 @@ trap_span_converter(PicturePtr dst,
 		return false;
 
 	if (dst->polyEdge == PolyEdgeSharp)
-		return mono_trap_span_converter(dst, src_x, src_y, ntrap, trap);
+		return mono_trap_span_converter(sna, dst, src_x, src_y, ntrap, trap);
 
-	sna = to_sna_from_drawable(dst->pDrawable);
 	if (!sna->render.check_composite_spans(sna, PictOpAdd, sna->render.white_picture, dst,
 					       dst->pCompositeClip->extents.x2 - dst->pCompositeClip->extents.x1,
 					       dst->pCompositeClip->extents.y2 - dst->pCompositeClip->extents.y1,
@@ -6795,11 +6806,11 @@ static void mark_damaged(PixmapPtr pixmap, struct sna_pixmap *priv,
 }
 
 static bool
-trap_mask_converter(PicturePtr picture,
+trap_mask_converter(struct sna *sna,
+		    PicturePtr picture,
 		    INT16 x, INT16 y,
 		    int ntrap, xTrap *trap)
 {
-	struct sna *sna;
 	struct tor tor;
 	ScreenPtr screen = picture->pDrawable->pScreen;
 	PixmapPtr scratch, pixmap;
@@ -6993,13 +7004,18 @@ trap_upload(PicturePtr picture,
 void
 sna_add_traps(PicturePtr picture, INT16 x, INT16 y, int n, xTrap *t)
 {
+	struct sna *sna;
+
 	DBG(("%s (%d, %d) x %d\n", __FUNCTION__, x, y, n));
 
-	if (is_gpu(picture->pDrawable)) {
-		if (trap_span_converter(picture, x, y, n, t))
+	sna = to_sna_from_drawable(picture->pDrawable);
+	if (is_gpu(sna, picture->pDrawable, PREFER_GPU_SPANS)) {
+		if (trap_span_converter(sna, picture, x, y, n, t))
 			return;
+	}
 
-		if (trap_mask_converter(picture, x, y, n, t))
+	if (is_gpu(sna, picture->pDrawable, PREFER_GPU_RENDER)) {
+		if (trap_mask_converter(sna, picture, x, y, n, t))
 			return;
 
 		if (trap_upload(picture, x, y, n, t))
@@ -7064,7 +7080,8 @@ project_triangle_onto_grid(const xTriangle *in,
 }
 
 static bool
-mono_triangles_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
+mono_triangles_span_converter(struct sna *sna,
+			      CARD8 op, PicturePtr src, PicturePtr dst,
 			      INT16 src_x, INT16 src_y,
 			      int count, xTriangle *tri)
 {
@@ -7075,7 +7092,7 @@ mono_triangles_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 	bool was_clear;
 	int n;
 
-	mono.sna = to_sna_from_drawable(dst->pDrawable);
+	mono.sna = sna;
 
 	dst_x = pixman_fixed_to_int(tri[0].p1.x);
 	dst_y = pixman_fixed_to_int(tri[0].p1.y);
@@ -7200,11 +7217,11 @@ mono_triangles_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 }
 
 static bool
-triangles_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
+triangles_span_converter(struct sna *sna,
+			 CARD8 op, PicturePtr src, PicturePtr dst,
 			 PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
 			 int count, xTriangle *tri)
 {
-	struct sna *sna;
 	struct sna_composite_spans_op tmp;
 	struct tor tor;
 	BoxRec extents;
@@ -7217,7 +7234,7 @@ triangles_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 		return false;
 
 	if (is_mono(dst, maskFormat))
-		return mono_triangles_span_converter(op, src, dst,
+		return mono_triangles_span_converter(sna, op, src, dst,
 						     src_x, src_y,
 						     count, tri);
 
@@ -7228,7 +7245,6 @@ triangles_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 		return false;
 	}
 
-	sna = to_sna_from_drawable(dst->pDrawable);
 	if (!sna->render.check_composite_spans(sna, op, src, dst, 0, 0, 0)) {
 		DBG(("%s: fallback -- composite spans not supported\n",
 		     __FUNCTION__));
@@ -7553,7 +7569,9 @@ sna_composite_triangles(CARD8 op,
 			 INT16 xSrc, INT16 ySrc,
 			 int n, xTriangle *tri)
 {
-	if (triangles_span_converter(op, src, dst, maskFormat,
+	struct sna *sna = to_sna_from_drawable(dst->pDrawable);
+
+	if (triangles_span_converter(sna, op, src, dst, maskFormat,
 				     xSrc, ySrc,
 				     n, tri))
 		return;
@@ -7567,11 +7585,11 @@ sna_composite_triangles(CARD8 op,
 }
 
 static bool
-tristrip_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
+tristrip_span_converter(struct sna *sna,
+			CARD8 op, PicturePtr src, PicturePtr dst,
 			PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
 			int count, xPointFixed *points)
 {
-	struct sna *sna;
 	struct sna_composite_spans_op tmp;
 	struct tor tor;
 	BoxRec extents;
@@ -7592,7 +7610,6 @@ tristrip_span_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 		return false;
 	}
 
-	sna = to_sna_from_drawable(dst->pDrawable);
 	if (!sna->render.check_composite_spans(sna, op, src, dst, 0, 0, 0)) {
 		DBG(("%s: fallback -- composite spans not supported\n",
 		     __FUNCTION__));
@@ -7833,7 +7850,9 @@ sna_composite_tristrip(CARD8 op,
 		       INT16 xSrc, INT16 ySrc,
 		       int n, xPointFixed *points)
 {
-	if (tristrip_span_converter(op, src, dst, maskFormat, xSrc, ySrc, n, points))
+	struct sna *sna = to_sna_from_drawable(dst->pDrawable);
+
+	if (tristrip_span_converter(sna, op, src, dst, maskFormat, xSrc, ySrc, n, points))
 		return;
 
 	tristrip_fallback(op, src, dst, maskFormat, xSrc, ySrc, n, points);
commit bec99de812ce6a1bbc2c8e4cfd05f4f74c560ea6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Feb 8 00:53:10 2013 +0000

    sna: Remove the bogus assertions on buffer domains
    
    Just a few lines earlier we already have the correct assertion that the
    buffer was not in the GPU domain, so had these two been correct, they
    would have still been redundant.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index ef8cdde..2801efc 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -2246,7 +2246,6 @@ static void kgem_finish_buffers(struct kgem *kgem)
 					list_init(&bo->base.request);
 					shrink->needs_flush = bo->base.dirty;
 
-					assert(bo->base.domain == DOMAIN_NONE);
 					bo->base.exec = NULL;
 					bo->base.rq = NULL;
 					bo->base.dirty = false;
@@ -2292,7 +2291,6 @@ static void kgem_finish_buffers(struct kgem *kgem)
 					list_init(&bo->base.request);
 					shrink->needs_flush = bo->base.dirty;
 
-					assert(bo->base.domain == DOMAIN_NONE);
 					bo->base.exec = NULL;
 					bo->base.rq = NULL;
 					bo->base.dirty = false;


More information about the xorg-commit mailing list