xf86-video-intel: 8 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/sna_accel.c src/sna/sna_render.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Dec 8 04:37:33 PST 2011


 src/sna/gen2_render.c |  108 ++++++++++++++++++++++++++++++++++++++++++--
 src/sna/gen3_render.c |  114 ++++++++++++++++++++++++++++++++++++++++++-----
 src/sna/gen4_render.c |  121 ++++++++++++++++++++++++++++++++++++++++++++++++--
 src/sna/gen5_render.c |  109 +++++++++++++++++++++++++++++++++++++++++++++
 src/sna/gen6_render.c |  109 +++++++++++++++++++++++++++++++++++++++++++++
 src/sna/gen7_render.c |  109 +++++++++++++++++++++++++++++++++++++++++++++
 src/sna/sna_accel.c   |    2 
 src/sna/sna_render.c  |    6 +-
 8 files changed, 656 insertions(+), 22 deletions(-)

New commits:
commit 84aaf1537cbd29e163346d03debc39f4623c69eb
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 8 12:36:08 2011 +0000

    sna/gen7: Reduce dst readbacks for unsupported sources
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 3159da3..68ec221 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2202,6 +2202,109 @@ try_blt(struct sna *sna, int width, int height)
 	return FALSE;
 }
 
+static bool
+is_solid(PicturePtr picture)
+{
+	return  picture->pDrawable->width == 1 &&
+		picture->pDrawable->height == 1 &&
+		picture->repeat;
+}
+
+static bool
+is_gradient(PicturePtr picture)
+{
+	if (picture->pDrawable)
+		return FALSE;
+
+	return picture->pSourcePict->type != SourcePictTypeSolidFill;
+}
+
+static bool
+source_fallback(PicturePtr p)
+{
+	return is_gradient(p) || !gen7_check_filter(p) || !gen7_check_repeat(p);
+}
+
+static bool
+gen7_composite_fallback(struct sna *sna,
+			PicturePtr src,
+			PicturePtr mask,
+			PicturePtr dst)
+{
+	struct sna_pixmap *priv;
+	PixmapPtr src_pixmap;
+	PixmapPtr mask_pixmap;
+	PixmapPtr dst_pixmap;
+
+	if (!gen7_check_dst_format(dst->format)) {
+		DBG(("%s: unknown destination format: %d\n",
+		     __FUNCTION__, dst->format));
+		return TRUE;
+	}
+
+	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
+	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
+	mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL;
+
+	/* If we are using the destination as a source and need to
+	 * readback in order to upload the source, do it all
+	 * on the cpu.
+	 */
+	if (src_pixmap == dst_pixmap && source_fallback(src)) {
+		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+	if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
+		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+
+	/* If anything is on the GPU, push everything out to the GPU */
+	priv = sna_pixmap(dst_pixmap);
+	if (priv && priv->gpu_damage) {
+		DBG(("%s: dst is already on the GPU, try to use GPU\n",
+		     __FUNCTION__));
+		return FALSE;
+	}
+
+	if (src_pixmap && !is_solid(src) && !source_fallback(src)) {
+		priv = sna_pixmap(src_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: src is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+	if (mask_pixmap && !is_solid(mask) && !source_fallback(mask)) {
+		priv = sna_pixmap(mask_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: mask is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+
+	/* However if the dst is not on the GPU and we need to
+	 * render one of the sources using the CPU, we may
+	 * as well do the entire operation in place onthe CPU.
+	 */
+	if (source_fallback(src)) {
+		DBG(("%s: dst is on the CPU and src will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	if (mask && source_fallback(mask)) {
+		DBG(("%s: dst is on the CPU and mask will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
+	     __FUNCTION__));
+	return FALSE;
+}
+
 static Bool
 gen7_render_composite(struct sna *sna,
 		      uint8_t op,
@@ -2240,6 +2343,9 @@ gen7_render_composite(struct sna *sna,
 			      width, height, tmp))
 		return TRUE;
 
+	if (gen7_composite_fallback(sna, src, mask, dst))
+		return FALSE;
+
 	if (need_tiling(sna, width, height))
 		return sna_tiling_composite(op, src, mask, dst,
 					    src_x, src_y,
@@ -2603,6 +2709,9 @@ gen7_render_composite_spans(struct sna *sna,
 	if (need_tiling(sna, width, height))
 		return FALSE;
 
+	if (gen7_composite_fallback(sna, src, NULL, dst))
+		return FALSE;
+
 	tmp->base.op = op;
 	if (!gen7_composite_set_target(&tmp->base, dst))
 		return FALSE;
commit 440ac68ec074e82818713773f3e2cb5d363862aa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 8 12:35:54 2011 +0000

    sna/gen6: Reduce dst readbacks for unsupported sources
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 5a889e7..cb62463 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2081,6 +2081,109 @@ try_blt(struct sna *sna, int width, int height)
 	return FALSE;
 }
 
+static bool
+is_solid(PicturePtr picture)
+{
+	return  picture->pDrawable->width == 1 &&
+		picture->pDrawable->height == 1 &&
+		picture->repeat;
+}
+
+static bool
+is_gradient(PicturePtr picture)
+{
+	if (picture->pDrawable)
+		return FALSE;
+
+	return picture->pSourcePict->type != SourcePictTypeSolidFill;
+}
+
+static bool
+source_fallback(PicturePtr p)
+{
+	return is_gradient(p) || !gen6_check_filter(p) || !gen6_check_repeat(p);
+}
+
+static bool
+gen6_composite_fallback(struct sna *sna,
+			PicturePtr src,
+			PicturePtr mask,
+			PicturePtr dst)
+{
+	struct sna_pixmap *priv;
+	PixmapPtr src_pixmap;
+	PixmapPtr mask_pixmap;
+	PixmapPtr dst_pixmap;
+
+	if (!gen6_check_dst_format(dst->format)) {
+		DBG(("%s: unknown destination format: %d\n",
+		     __FUNCTION__, dst->format));
+		return TRUE;
+	}
+
+	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
+	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
+	mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL;
+
+	/* If we are using the destination as a source and need to
+	 * readback in order to upload the source, do it all
+	 * on the cpu.
+	 */
+	if (src_pixmap == dst_pixmap && source_fallback(src)) {
+		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+	if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
+		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+
+	/* If anything is on the GPU, push everything out to the GPU */
+	priv = sna_pixmap(dst_pixmap);
+	if (priv && priv->gpu_damage) {
+		DBG(("%s: dst is already on the GPU, try to use GPU\n",
+		     __FUNCTION__));
+		return FALSE;
+	}
+
+	if (src_pixmap && !is_solid(src) && !source_fallback(src)) {
+		priv = sna_pixmap(src_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: src is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+	if (mask_pixmap && !is_solid(mask) && !source_fallback(mask)) {
+		priv = sna_pixmap(mask_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: mask is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+
+	/* However if the dst is not on the GPU and we need to
+	 * render one of the sources using the CPU, we may
+	 * as well do the entire operation in place onthe CPU.
+	 */
+	if (source_fallback(src)) {
+		DBG(("%s: dst is on the CPU and src will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	if (mask && source_fallback(mask)) {
+		DBG(("%s: dst is on the CPU and mask will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
+	     __FUNCTION__));
+	return FALSE;
+}
+
 static Bool
 gen6_render_composite(struct sna *sna,
 		      uint8_t op,
@@ -2119,6 +2222,9 @@ gen6_render_composite(struct sna *sna,
 			      width, height, tmp))
 		return TRUE;
 
+	if (gen6_composite_fallback(sna, src, mask, dst))
+		return FALSE;
+
 	if (need_tiling(sna, width, height))
 		return sna_tiling_composite(op, src, mask, dst,
 					    src_x, src_y,
@@ -2482,6 +2588,9 @@ gen6_render_composite_spans(struct sna *sna,
 	if (need_tiling(sna, width, height))
 		return FALSE;
 
+	if (gen6_composite_fallback(sna, src, NULL, dst))
+		return FALSE;
+
 	tmp->base.op = op;
 	if (!gen6_composite_set_target(&tmp->base, dst))
 		return FALSE;
commit bc68211d18356c4a0e011ac360665d600de9fa30
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 8 12:35:39 2011 +0000

    sna/gen5: Reduce dst readbacks for unsupported sources
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 8b683a8..e8a9606 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1921,6 +1921,109 @@ try_blt(struct sna *sna, PicturePtr source, int width, int height)
 	return picture_is_cpu(source);
 }
 
+static bool
+is_solid(PicturePtr picture)
+{
+	return  picture->pDrawable->width == 1 &&
+		picture->pDrawable->height == 1 &&
+		picture->repeat;
+}
+
+static bool
+is_gradient(PicturePtr picture)
+{
+	if (picture->pDrawable)
+		return FALSE;
+
+	return picture->pSourcePict->type != SourcePictTypeSolidFill;
+}
+
+static bool
+source_fallback(PicturePtr p)
+{
+	return is_gradient(p) || !gen5_check_filter(p) || !gen5_check_repeat(p);
+}
+
+static bool
+gen5_composite_fallback(struct sna *sna,
+			PicturePtr src,
+			PicturePtr mask,
+			PicturePtr dst)
+{
+	struct sna_pixmap *priv;
+	PixmapPtr src_pixmap;
+	PixmapPtr mask_pixmap;
+	PixmapPtr dst_pixmap;
+
+	if (!gen5_check_dst_format(dst->format)) {
+		DBG(("%s: unknown destination format: %d\n",
+		     __FUNCTION__, dst->format));
+		return TRUE;
+	}
+
+	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
+	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
+	mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL;
+
+	/* If we are using the destination as a source and need to
+	 * readback in order to upload the source, do it all
+	 * on the cpu.
+	 */
+	if (src_pixmap == dst_pixmap && source_fallback(src)) {
+		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+	if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
+		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+
+	/* If anything is on the GPU, push everything out to the GPU */
+	priv = sna_pixmap(dst_pixmap);
+	if (priv && priv->gpu_damage) {
+		DBG(("%s: dst is already on the GPU, try to use GPU\n",
+		     __FUNCTION__));
+		return FALSE;
+	}
+
+	if (src_pixmap && !is_solid(src) && !source_fallback(src)) {
+		priv = sna_pixmap(src_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: src is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+	if (mask_pixmap && !is_solid(mask) && !source_fallback(mask)) {
+		priv = sna_pixmap(mask_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: mask is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+
+	/* However if the dst is not on the GPU and we need to
+	 * render one of the sources using the CPU, we may
+	 * as well do the entire operation in place onthe CPU.
+	 */
+	if (source_fallback(src)) {
+		DBG(("%s: dst is on the CPU and src will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	if (mask && source_fallback(mask)) {
+		DBG(("%s: dst is on the CPU and mask will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
+	     __FUNCTION__));
+	return FALSE;
+}
+
 static Bool
 gen5_render_composite(struct sna *sna,
 		      uint8_t op,
@@ -1950,6 +2053,9 @@ gen5_render_composite(struct sna *sna,
 			      width, height, tmp))
 		return TRUE;
 
+	if (gen5_composite_fallback(sna, src, mask, dst))
+		return FALSE;
+
 	if (need_tiling(sna, width, height))
 		return sna_tiling_composite(op, src, mask, dst,
 					    src_x, src_y,
@@ -2312,6 +2418,9 @@ gen5_render_composite_spans(struct sna *sna,
 	if (need_tiling(sna, width, height))
 		return FALSE;
 
+	if (gen5_composite_fallback(sna, src, NULL, dst))
+		return FALSE;
+
 	tmp->base.op = op;
 	if (!gen5_composite_set_target(dst, &tmp->base))
 		return FALSE;
commit a5df7c28e458c2f2b173fe5d745f447087eb8c6f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 8 12:35:22 2011 +0000

    sna/gen4: Reduce dst readbacks for unsupported sources
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 5e9bd37..73f659f 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -585,6 +585,7 @@ static uint32_t gen4_check_filter(PicturePtr picture)
 	case PictFilterBilinear:
 		return TRUE;
 	default:
+		DBG(("%s: unknown filter: %d\n", __FUNCTION__, picture->filter));
 		return FALSE;
 	}
 }
@@ -617,6 +618,8 @@ static bool gen4_check_repeat(PicturePtr picture)
 	case RepeatReflect:
 		return TRUE;
 	default:
+		DBG(("%s: unknown repeat: %d\n",
+		     __FUNCTION__, picture->repeatType));
 		return FALSE;
 	}
 }
@@ -1735,17 +1738,23 @@ gen4_composite_picture(struct sna *sna,
 	if (sna_picture_is_solid(picture, &color))
 		return gen4_composite_solid_init(sna, channel, color);
 
-	if (picture->pDrawable == NULL)
+	if (picture->pDrawable == NULL) {
+		DBG(("%s: procedural source fixup\n", __FUNCTION__));
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
+	}
 
-	if (!gen4_check_repeat(picture))
+	if (!gen4_check_repeat(picture)) {
+		DBG(("%s: unknown repeat mode fixup\n", __FUNCTION__));
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
+	}
 
-	if (!gen4_check_filter(picture))
+	if (!gen4_check_filter(picture)) {
+		DBG(("%s: unhandled filter fixup\n", __FUNCTION__));
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
+	}
 
 	channel->repeat = picture->repeat ? picture->repeatType : RepeatNone;
 	channel->filter = picture->filter;
@@ -1884,6 +1893,109 @@ try_blt(struct sna *sna,
 	return picture_is_cpu(source);
 }
 
+static bool
+is_solid(PicturePtr picture)
+{
+	return  picture->pDrawable->width == 1 &&
+		picture->pDrawable->height == 1 &&
+		picture->repeat;
+}
+
+static bool
+is_gradient(PicturePtr picture)
+{
+	if (picture->pDrawable)
+		return FALSE;
+
+	return picture->pSourcePict->type != SourcePictTypeSolidFill;
+}
+
+static bool
+source_fallback(PicturePtr p)
+{
+	return is_gradient(p) || !gen4_check_filter(p) || !gen4_check_repeat(p);
+}
+
+static bool
+gen4_composite_fallback(struct sna *sna,
+			PicturePtr src,
+			PicturePtr mask,
+			PicturePtr dst)
+{
+	struct sna_pixmap *priv;
+	PixmapPtr src_pixmap;
+	PixmapPtr mask_pixmap;
+	PixmapPtr dst_pixmap;
+
+	if (!gen4_check_dst_format(dst->format)) {
+		DBG(("%s: unknown destination format: %d\n",
+		     __FUNCTION__, dst->format));
+		return TRUE;
+	}
+
+	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
+	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
+	mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL;
+
+	/* If we are using the destination as a source and need to
+	 * readback in order to upload the source, do it all
+	 * on the cpu.
+	 */
+	if (src_pixmap == dst_pixmap && source_fallback(src)) {
+		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+	if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
+		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+
+	/* If anything is on the GPU, push everything out to the GPU */
+	priv = sna_pixmap(dst_pixmap);
+	if (priv && priv->gpu_damage) {
+		DBG(("%s: dst is already on the GPU, try to use GPU\n",
+		     __FUNCTION__));
+		return FALSE;
+	}
+
+	if (src_pixmap && !is_solid(src) && !source_fallback(src)) {
+		priv = sna_pixmap(src_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: src is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+	if (mask_pixmap && !is_solid(mask) && !source_fallback(mask)) {
+		priv = sna_pixmap(mask_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: mask is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+
+	/* However if the dst is not on the GPU and we need to
+	 * render one of the sources using the CPU, we may
+	 * as well do the entire operation in place onthe CPU.
+	 */
+	if (source_fallback(src)) {
+		DBG(("%s: dst is on the CPU and src will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	if (mask && source_fallback(mask)) {
+		DBG(("%s: dst is on the CPU and mask will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
+	     __FUNCTION__));
+	return FALSE;
+}
+
 static Bool
 gen4_render_composite(struct sna *sna,
 		      uint8_t op,
@@ -1922,6 +2034,9 @@ gen4_render_composite(struct sna *sna,
 			      width, height, tmp))
 		return TRUE;
 
+	if (gen4_composite_fallback(sna, src, mask, dst))
+		return FALSE;
+
 	if (need_tiling(sna, width, height))
 		return sna_tiling_composite(op, src, mask, dst,
 					    src_x, src_y,
commit cc8cab649c0a4788803d2c62f186142ec7152b89
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 8 12:34:58 2011 +0000

    sna/gen3: Reduce readbacks on dst for unsupported sources
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index d23f422..ea9d40a 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -305,9 +305,12 @@ static uint32_t gen3_gradient_repeat(uint32_t repeat)
 #undef REPEAT
 }
 
-static Bool gen3_check_repeat(uint32_t repeat)
+static Bool gen3_check_repeat(PicturePtr p)
 {
-	switch (repeat) {
+	if (!p->repeat)
+		return TRUE;
+
+	switch (p->repeatType) {
 	case RepeatNone:
 	case RepeatNormal:
 	case RepeatPad:
@@ -2074,7 +2077,7 @@ gen3_composite_picture(struct sna *sna,
 	if (sna_picture_is_solid(picture, &color))
 		return gen3_init_solid(channel, color);
 
-	if (!gen3_check_repeat(picture->repeat))
+	if (!gen3_check_repeat(picture))
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
 
@@ -2225,6 +2228,101 @@ static inline bool is_constant_ps(uint32_t type)
 	}
 }
 
+
+static bool
+is_solid(PicturePtr picture)
+{
+	return  picture->pDrawable->width == 1 &&
+		picture->pDrawable->height == 1 &&
+		picture->repeat;
+}
+
+static bool
+source_fallback(PicturePtr p)
+{
+	return !gen3_check_filter(p->filter) || !gen3_check_repeat(p);
+}
+
+static bool
+gen3_composite_fallback(struct sna *sna,
+			PicturePtr src,
+			PicturePtr mask,
+			PicturePtr dst)
+{
+	struct sna_pixmap *priv;
+	PixmapPtr src_pixmap;
+	PixmapPtr mask_pixmap;
+	PixmapPtr dst_pixmap;
+
+	if (!gen3_check_dst_format(dst->format)) {
+		DBG(("%s: unknown destination format: %d\n",
+		     __FUNCTION__, dst->format));
+		return TRUE;
+	}
+
+	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
+	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
+	mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL;
+
+	/* If we are using the destination as a source and need to
+	 * readback in order to upload the source, do it all
+	 * on the cpu.
+	 */
+	if (src_pixmap == dst_pixmap && source_fallback(src)) {
+		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+	if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
+		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+
+	/* If anything is on the GPU, push everything out to the GPU */
+	priv = sna_pixmap(dst_pixmap);
+	if (priv && priv->gpu_damage) {
+		DBG(("%s: dst is already on the GPU, try to use GPU\n",
+		     __FUNCTION__));
+		return FALSE;
+	}
+
+	if (src_pixmap && !is_solid(src) && !source_fallback(src)) {
+		priv = sna_pixmap(src_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: src is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+	if (mask_pixmap && !is_solid(mask) && !source_fallback(mask)) {
+		priv = sna_pixmap(mask_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: mask is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+
+	/* However if the dst is not on the GPU and we need to
+	 * render one of the sources using the CPU, we may
+	 * as well do the entire operation in place onthe CPU.
+	 */
+	if (source_fallback(src)) {
+		DBG(("%s: dst is on the CPU and src will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	if (mask && source_fallback(mask)) {
+		DBG(("%s: dst is on the CPU and mask will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
+	     __FUNCTION__));
+	return FALSE;
+}
+
 static Bool
 gen3_render_composite(struct sna *sna,
 		      uint8_t op,
@@ -2269,11 +2367,8 @@ gen3_render_composite(struct sna *sna,
 			      tmp))
 		return TRUE;
 
-	if (!gen3_check_dst_format(dst->format)) {
-		DBG(("%s: fallback due to unhandled dst format: %x\n",
-		     __FUNCTION__, dst->format));
+	if (gen3_composite_fallback(sna, src, mask, dst))
 		return FALSE;
-	}
 
 	if (need_tiling(sna, width, height))
 		return sna_tiling_composite(op, src, mask, dst,
@@ -2812,11 +2907,8 @@ gen3_render_composite_spans(struct sna *sna,
 		return FALSE;
 	}
 
-	if (!gen3_check_dst_format(dst->format)) {
-		DBG(("%s: fallback due to unhandled dst format: %x\n",
-		     __FUNCTION__, dst->format));
+	if (gen3_composite_fallback(sna, src, NULL, dst))
 		return FALSE;
-	}
 
 	if (need_tiling(sna, width, height))
 		return FALSE;
commit e5bc0c823b8fd46b3f851c5e9a4b4de39cda9a91
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 8 12:34:34 2011 +0000

    sna/gen2: Avoid readbacks for unsupported sources
    
    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 e97e2d7..d35f2da 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1238,6 +1238,109 @@ try_blt(struct sna *sna,
 	return is_cpu(source->pDrawable);
 }
 
+static bool
+is_solid(PicturePtr picture)
+{
+	return  picture->pDrawable->width == 1 &&
+		picture->pDrawable->height == 1 &&
+		picture->repeat;
+}
+
+static bool
+is_gradient(PicturePtr picture)
+{
+	if (picture->pDrawable)
+		return FALSE;
+
+	return picture->pSourcePict->type != SourcePictTypeSolidFill;
+}
+
+static bool
+source_fallback(PicturePtr p)
+{
+	return is_gradient(p) || !gen2_check_filter(p) || !gen2_check_repeat(p);
+}
+
+static bool
+gen2_composite_fallback(struct sna *sna,
+			PicturePtr src,
+			PicturePtr mask,
+			PicturePtr dst)
+{
+	struct sna_pixmap *priv;
+	PixmapPtr src_pixmap;
+	PixmapPtr mask_pixmap;
+	PixmapPtr dst_pixmap;
+
+	if (!gen2_check_dst_format(dst->format)) {
+		DBG(("%s: unknown destination format: %d\n",
+		     __FUNCTION__, dst->format));
+		return TRUE;
+	}
+
+	dst_pixmap = get_drawable_pixmap(dst->pDrawable);
+	src_pixmap = src->pDrawable ? get_drawable_pixmap(src->pDrawable) : NULL;
+	mask_pixmap = (mask && mask->pDrawable) ? get_drawable_pixmap(mask->pDrawable) : NULL;
+
+	/* If we are using the destination as a source and need to
+	 * readback in order to upload the source, do it all
+	 * on the cpu.
+	 */
+	if (src_pixmap == dst_pixmap && source_fallback(src)) {
+		DBG(("%s: src is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+	if (mask_pixmap == dst_pixmap && source_fallback(mask)) {
+		DBG(("%s: mask is dst and will fallback\n",__FUNCTION__));
+		return TRUE;
+	}
+
+	/* If anything is on the GPU, push everything out to the GPU */
+	priv = sna_pixmap(dst_pixmap);
+	if (priv && priv->gpu_damage) {
+		DBG(("%s: dst is already on the GPU, try to use GPU\n",
+		     __FUNCTION__));
+		return FALSE;
+	}
+
+	if (src_pixmap && !is_solid(src) && !source_fallback(src)) {
+		priv = sna_pixmap(src_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: src is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+	if (mask_pixmap && !is_solid(mask) && !source_fallback(mask)) {
+		priv = sna_pixmap(mask_pixmap);
+		if (priv && priv->gpu_damage) {
+			DBG(("%s: mask is already on the GPU, try to use GPU\n",
+			     __FUNCTION__));
+			return FALSE;
+		}
+	}
+
+	/* However if the dst is not on the GPU and we need to
+	 * render one of the sources using the CPU, we may
+	 * as well do the entire operation in place onthe CPU.
+	 */
+	if (source_fallback(src)) {
+		DBG(("%s: dst is on the CPU and src will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	if (mask && source_fallback(mask)) {
+		DBG(("%s: dst is on the CPU and mask will fallback\n",
+		     __FUNCTION__));
+		return TRUE;
+	}
+
+	DBG(("%s: dst is not on the GPU and the operation should not fallback\n",
+	     __FUNCTION__));
+	return FALSE;
+}
+
 static Bool
 gen2_render_composite(struct sna *sna,
 		      uint8_t op,
@@ -1282,11 +1385,8 @@ gen2_render_composite(struct sna *sna,
 			      tmp))
 		return TRUE;
 
-	if (!gen2_check_dst_format(dst->format)) {
-		DBG(("%s: fallback due to unhandled dst format: %x\n",
-		     __FUNCTION__, dst->format));
+	if (gen2_composite_fallback(sna, src, mask, dst))
 		return FALSE;
-	}
 
 	if (need_tiling(sna, width, height))
 		return sna_tiling_composite(op, src, mask, dst,
commit 874c722c86b06ac0aa10e6943d3faf76fcb751be
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 8 12:07:28 2011 +0000

    sna: Beware flushing partial buffers before they are written
    
    A partial buffer is considered finished upon the next batch submission,
    so one needs to be careful that it is completely written to before such
    an event is triggered. move-to-cpu is such a trigger as demonstrated by
    the picture fixup routine for handling convolution filters.
    
    Reported-by: Victor Machado <machado.prx at gmail.com>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=43607
    Signed-off-by: Chris Wilson <ickle at crestline.(none)>

diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index cf227c6..13c0526 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -900,6 +900,9 @@ sna_render_picture_fixup(struct sna *sna,
 		     __FUNCTION__, channel->pict_format, pitch, picture->format));
 	}
 
+	if (picture->pDrawable)
+		sna_drawable_move_to_cpu(picture->pDrawable, false);
+
 	channel->bo = kgem_create_buffer(&sna->kgem,
 					 pitch*h, KGEM_BUFFER_WRITE,
 					 &ptr);
@@ -923,9 +926,6 @@ sna_render_picture_fixup(struct sna *sna,
 		return 0;
 	}
 
-	if (picture->pDrawable)
-		sna_drawable_move_to_cpu(picture->pDrawable, false);
-
 	src = image_from_pict(picture, FALSE, &dx, &dy);
 	if (src == NULL) {
 		pixman_image_unref(dst);
commit 6ccb114a7e685c69fb388ebd119393455b315c36
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 7 21:09:31 2011 +0000

    sna: Prefer to use our pixmap upload paths
    
    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 c467f74..e1905d1 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1385,7 +1385,7 @@ sna_put_zpixmap_blt(DrawablePtr drawable, GCPtr gc, RegionPtr region,
 	int16_t dx, dy;
 	int n;
 
-	if (!priv->gpu_bo)
+	if (!priv)
 		return false;
 
 	if (priv->gpu_only)


More information about the xorg-commit mailing list