xf86-video-intel: 2 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/gen8_render.c src/sna/sna_blt.c

Chris Wilson ickle at kemper.freedesktop.org
Fri Apr 4 05:55:49 PDT 2014


 src/sna/gen2_render.c |   12 ++++
 src/sna/gen3_render.c |   12 ++++
 src/sna/gen4_render.c |   12 ++++
 src/sna/gen5_render.c |   12 ++++
 src/sna/gen6_render.c |   12 ++++
 src/sna/gen7_render.c |   12 ++++
 src/sna/gen8_render.c |   12 ++++
 src/sna/sna_blt.c     |  138 ++++++++++++++++++++++++++++++++++++++++++++++++--
 8 files changed, 217 insertions(+), 5 deletions(-)

New commits:
commit 6e86e84da1c8049a150eb6b5780526fea57e0f9d
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 4 12:41:25 2014 +0100

    sna: Precompute OVER/ADD with solids to convert it into a BLT operation
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index b83e6b2..f68d951 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -815,6 +815,26 @@ sna_picture_is_solid(PicturePtr picture, uint32_t *color)
 }
 
 static bool
+pixel_is_transparent(uint32_t pixel, uint32_t format)
+{
+	unsigned int abits;
+
+	abits = PICT_FORMAT_A(format);
+	if (!abits)
+		return false;
+
+	if (PICT_FORMAT_TYPE(format) == PICT_TYPE_A ||
+	    PICT_FORMAT_TYPE(format) == PICT_TYPE_BGRA) {
+		return (pixel & ((1 << abits) - 1)) == 0;
+	} else if (PICT_FORMAT_TYPE(format) == PICT_TYPE_ARGB ||
+		   PICT_FORMAT_TYPE(format) == PICT_TYPE_ABGR) {
+		unsigned int ashift = PICT_FORMAT_BPP(format) - abits;
+		return (pixel >> ashift) == 0;
+	} else
+		return false;
+}
+
+static bool
 pixel_is_opaque(uint32_t pixel, uint32_t format)
 {
 	unsigned int abits;
@@ -868,6 +888,16 @@ is_white(PicturePtr picture)
 		return pixel_is_white(get_pixel(picture), picture->format);
 }
 
+static bool
+is_transparent(PicturePtr picture)
+{
+	if (picture->pSourcePict) {
+		PictSolidFill *fill = (PictSolidFill *) picture->pSourcePict;
+		return fill->color == 0;
+	} else
+		return pixel_is_transparent(get_pixel(picture), picture->format);
+}
+
 bool
 sna_composite_mask_is_opaque(PicturePtr mask)
 {
@@ -2361,6 +2391,71 @@ is_clear(PixmapPtr pixmap)
 	return priv && priv->clear;
 }
 
+static inline uint32_t
+over(uint32_t src, uint32_t dst)
+{
+	uint32_t a = ~src >> 24;
+
+#define G_SHIFT 8
+#define RB_MASK 0xff00ff
+#define RB_ONE_HALF 0x800080
+#define RB_MASK_PLUS_ONE 0x10000100
+
+#define UN8_rb_MUL_UN8(x, a, t) do {				\
+	t  = ((x) & RB_MASK) * (a);				\
+	t += RB_ONE_HALF;					\
+	x = (t + ((t >> G_SHIFT) & RB_MASK)) >> G_SHIFT;	\
+	x &= RB_MASK;						\
+} while (0)
+
+#define UN8_rb_ADD_UN8_rb(x, y, t) do {				\
+	t = ((x) + (y));					\
+	t |= RB_MASK_PLUS_ONE - ((t >> G_SHIFT) & RB_MASK);	\
+	x = (t & RB_MASK);					\
+} while (0)
+
+#define UN8x4_MUL_UN8_ADD_UN8x4(x, a, y) do {			\
+	uint32_t r1__, r2__, r3__, t__;				\
+	\
+	r1__ = (x);						\
+	r2__ = (y) & RB_MASK;					\
+	UN8_rb_MUL_UN8(r1__, (a), t__);				\
+	UN8_rb_ADD_UN8_rb(r1__, r2__, t__);			\
+	\
+	r2__ = (x) >> G_SHIFT;					\
+	r3__ = ((y) >> G_SHIFT) & RB_MASK;			\
+	UN8_rb_MUL_UN8(r2__, (a), t__);				\
+	UN8_rb_ADD_UN8_rb(r2__, r3__, t__);			\
+	\
+	(x) = r1__ | (r2__ << G_SHIFT);				\
+} while (0)
+
+	UN8x4_MUL_UN8_ADD_UN8x4(dst, a, src);
+
+	return dst;
+}
+
+static inline uint32_t
+add(uint32_t src, uint32_t dst)
+{
+#define UN8x4_ADD_UN8x4(x, y) do {				\
+	uint32_t r1__, r2__, r3__, t__;				\
+	\
+	r1__ = (x) & RB_MASK;					\
+	r2__ = (y) & RB_MASK;					\
+	UN8_rb_ADD_UN8_rb(r1__, r2__, t__);			\
+	\
+	r2__ = ((x) >> G_SHIFT) & RB_MASK;			\
+	r3__ = ((y) >> G_SHIFT) & RB_MASK;			\
+	UN8_rb_ADD_UN8_rb(r2__, r3__, t__);			\
+	\
+	x = r1__ | (r2__ << G_SHIFT);				\
+} while (0)
+
+	UN8x4_ADD_UN8x4(src, dst);
+	return src;
+}
+
 bool
 sna_blt_composite(struct sna *sna,
 		  uint32_t op,
@@ -2459,12 +2554,40 @@ clear:
 	}
 
 	if (is_solid(src)) {
+		if ((op == PictOpOver || op == PictOpAdd) && is_transparent(src)) {
+			sna_pixmap(tmp->dst.pixmap)->clear = was_clear;
+			return prepare_blt_nop(sna, tmp);
+		}
 		if (op == PictOpOver && is_opaque_solid(src))
 			op = PictOpSrc;
 		if (op == PictOpAdd && is_white(src))
 			op = PictOpSrc;
-		if (was_clear && (op == PictOpAdd || op == PictOpOver))
-			op = PictOpSrc;
+		if (was_clear && (op == PictOpAdd || op == PictOpOver)) {
+			if (sna_pixmap(tmp->dst.pixmap)->clear_color == 0)
+				op = PictOpSrc;
+			if (op == PictOpOver) {
+				color = over(get_solid_color(src, PICT_a8r8g8b8),
+					     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+							   dst->format, PICT_a8r8g8b8));
+				op = PictOpSrc;
+				DBG(("%s: precomputing solid OVER (%08x, %08x) -> %08x\n",
+				     get_solid_color(src, PICT_a8r8g8b8),
+				     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+						   dst->format, PICT_a8r8g8b8),
+				     color));
+			}
+			if (op == PictOpAdd) {
+				color = add(get_solid_color(src, PICT_a8r8g8b8),
+					    color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+							  dst->format, PICT_a8r8g8b8));
+				op = PictOpSrc;
+				DBG(("%s: precomputing solid ADD (%08x, %08x) -> %08x\n",
+				     get_solid_color(src, PICT_a8r8g8b8),
+				     color_convert(sna_pixmap(tmp->dst.pixmap)->clear_color,
+						   dst->format, PICT_a8r8g8b8),
+				     color));
+			}
+		}
 		if (op == PictOpOutReverse && is_opaque_solid(src))
 			goto clear;
 
commit 31a4c7bc13c5f4560482b450b9ee4788a58930cd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Apr 4 10:46:48 2014 +0100

    sna/gen2+: Replace composite sources with solids where possible
    
    If the composite reads entirely from within a large pixmap which is a
    clear color, just replace the source with a solid.
    
    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 e3931e3..698ed99 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1557,6 +1557,18 @@ gen2_composite_picture(struct sna *sna,
 		y += dy;
 		channel->transform = NULL;
 		channel->filter = PictFilterNearest;
+
+		if (channel->repeat &&
+		    (x >= 0 &&
+		     y >= 0 &&
+		     x + w < pixmap->drawable.width &&
+		     y + h < pixmap->drawable.height)) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv->clear) {
+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+				return gen2_composite_solid_init(sna, channel, priv->clear_color);
+			}
+		}
 	} else
 		channel->transform = picture->transform;
 
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index bb98beb..a30ee44 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3093,6 +3093,18 @@ gen3_composite_picture(struct sna *sna,
 		y += dy;
 		channel->transform = NULL;
 		channel->filter = PictFilterNearest;
+
+		if (channel->repeat ||
+		    (x >= 0 &&
+		     y >= 0 &&
+		     x + w < pixmap->drawable.width &&
+		     y + h < pixmap->drawable.height)) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv->clear) {
+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+				return gen3_init_solid(channel, priv->clear_color);
+			}
+		}
 	} else {
 		channel->transform = picture->transform;
 		channel->is_affine = sna_transform_is_affine(picture->transform);
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 88db06e..9994bf5 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1584,6 +1584,18 @@ gen4_composite_picture(struct sna *sna,
 		y += dy;
 		channel->transform = NULL;
 		channel->filter = PictFilterNearest;
+
+		if (channel->repeat &&
+		    (x >= 0 &&
+		     y >= 0 &&
+		     x + w < pixmap->drawable.width &&
+		     y + h < pixmap->drawable.height)) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv->clear) {
+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+				return gen4_channel_init_solid(sna, channel, priv->clear_color);
+			}
+		}
 	} else
 		channel->transform = picture->transform;
 
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 5508d49..6408eec 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1523,6 +1523,18 @@ gen5_composite_picture(struct sna *sna,
 		y += dy;
 		channel->transform = NULL;
 		channel->filter = PictFilterNearest;
+
+		if (channel->repeat ||
+		    (x >= 0 &&
+		     y >= 0 &&
+		     x + w < pixmap->drawable.width &&
+		     y + h < pixmap->drawable.height)) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv->clear) {
+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+				return gen4_channel_init_solid(sna, channel, priv->clear_color);
+			}
+		}
 	} else
 		channel->transform = picture->transform;
 
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index f1f7946..867108b 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -1773,6 +1773,18 @@ gen6_composite_picture(struct sna *sna,
 		y += dy;
 		channel->transform = NULL;
 		channel->filter = PictFilterNearest;
+
+		if (channel->repeat &&
+		    (x >= 0 &&
+		     y >= 0 &&
+		     x + w < pixmap->drawable.width &&
+		     y + h < pixmap->drawable.height)) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv->clear) {
+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+				return gen4_channel_init_solid(sna, channel, priv->clear_color);
+			}
+		}
 	} else
 		channel->transform = picture->transform;
 
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 6c1fe26..c7ce70c 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2036,6 +2036,18 @@ gen7_composite_picture(struct sna *sna,
 		y += dy;
 		channel->transform = NULL;
 		channel->filter = PictFilterNearest;
+
+		if (channel->repeat ||
+		    (x >= 0 &&
+		     y >= 0 &&
+		     x + w < pixmap->drawable.width &&
+		     y + h < pixmap->drawable.height)) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv->clear) {
+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+				return gen4_channel_init_solid(sna, channel, priv->clear_color);
+			}
+		}
 	} else
 		channel->transform = picture->transform;
 
diff --git a/src/sna/gen8_render.c b/src/sna/gen8_render.c
index 9e63483..0c851c8 100644
--- a/src/sna/gen8_render.c
+++ b/src/sna/gen8_render.c
@@ -1813,6 +1813,18 @@ gen8_composite_picture(struct sna *sna,
 		y += dy;
 		channel->transform = NULL;
 		channel->filter = PictFilterNearest;
+
+		if (channel->repeat ||
+		    (x >= 0 &&
+		     y >= 0 &&
+		     x + w < pixmap->drawable.width &&
+		     y + h < pixmap->drawable.height)) {
+			struct sna_pixmap *priv = sna_pixmap(pixmap);
+			if (priv->clear) {
+				DBG(("%s: converting large pixmap source into solid [%08x]\n", __FUNCTION__, priv->clear_color));
+				return gen4_channel_init_solid(sna, channel, priv->clear_color);
+			}
+		}
 	} else
 		channel->transform = picture->transform;
 
diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c
index c621977..b83e6b2 100644
--- a/src/sna/sna_blt.c
+++ b/src/sna/sna_blt.c
@@ -2564,9 +2564,14 @@ fill:
 
 	src_pixmap = get_drawable_pixmap(src->pDrawable);
 	if (is_clear(src_pixmap)) {
-		color = color_convert(sna_pixmap(src_pixmap)->clear_color,
-				      src->format, tmp->dst.format);
-		goto fill;
+		if (src->repeat ||
+		    (x >= 0 && y >= 0 &&
+		     x + width  < src_pixmap->drawable.width &&
+		     y + height < src_pixmap->drawable.height)) {
+			color = color_convert(sna_pixmap(src_pixmap)->clear_color,
+					      src->format, tmp->dst.format);
+			goto fill;
+		}
 	}
 
 	alpha_fixup = 0;


More information about the xorg-commit mailing list