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

Chris Wilson ickle at kemper.freedesktop.org
Sun Mar 25 15:12:01 PDT 2012


 src/sna/gen2_render.c |   24 ++++++++++---
 src/sna/gen3_render.c |   29 +++++++++++-----
 src/sna/gen4_render.c |   21 +++++++++---
 src/sna/gen5_render.c |   24 ++++++++++---
 src/sna/gen6_render.c |   24 ++++++++++---
 src/sna/gen7_render.c |   24 ++++++++++---
 src/sna/sna_render.c  |   86 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/sna/sna_render.h  |    8 ++++
 8 files changed, 201 insertions(+), 39 deletions(-)

New commits:
commit 62f9833298ea936eaefe973eca04b1dde858fbd8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sun Mar 25 21:25:15 2012 +0100

    sna/gen2+: Approximate expensive gradients when using imprecise rendering
    
    If we lack the ability to use a shader to compute the gradients
    per-pixel, we need to use pixman to render a fallback texture. We can
    reduce the size of this texture and upsample to reduce the cost with
    hopefully imperceptible loss of quality.
    
    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 6907dd6..0ad346e 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1310,7 +1310,8 @@ gen2_composite_picture(struct sna *sna,
 		       struct sna_composite_channel *channel,
 		       int x, int y,
 		       int w, int h,
-		       int dst_x, int dst_y)
+		       int dst_x, int dst_y,
+		       bool precise)
 {
 	PixmapPtr pixmap;
 	uint32_t color;
@@ -1343,6 +1344,8 @@ gen2_composite_picture(struct sna *sna,
 	}
 
 	if (picture->pDrawable == NULL) {
+		int ret;
+
 		if (picture->pSourcePict->type == SourcePictTypeLinear)
 			return gen2_composite_linear_init(sna, picture, channel,
 							  x, y,
@@ -1351,8 +1354,14 @@ gen2_composite_picture(struct sna *sna,
 
 		DBG(("%s -- fallback, unhandled source %d\n",
 		     __FUNCTION__, picture->pSourcePict->type));
-		return sna_render_picture_fixup(sna, picture, channel,
-						x, y, w, h, dst_x, dst_y);
+		ret = -1;
+		if (!precise)
+			ret = sna_render_picture_approximate_gradient(sna, picture, channel,
+								      x, y, w, h, dst_x, dst_y);
+		if (ret == -1)
+			ret = sna_render_picture_fixup(sna, picture, channel,
+						       x, y, w, h, dst_x, dst_y);
+		return ret;
 	}
 
 	if (picture->alphaMap) {
@@ -1765,7 +1774,8 @@ gen2_render_composite(struct sna *sna,
 	switch (gen2_composite_picture(sna, src, &tmp->src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
@@ -1781,7 +1791,8 @@ gen2_render_composite(struct sna *sna,
 			switch (gen2_composite_picture(sna, mask, &tmp->mask,
 						       mask_x, mask_y,
 						       width,  height,
-						       dst_x,  dst_y)) {
+						       dst_x,  dst_y,
+						       dst->polyMode == PolyModePrecise)) {
 			case -1:
 				goto cleanup_src;
 			case 0:
@@ -2229,7 +2240,8 @@ gen2_render_composite_spans(struct sna *sna,
 	switch (gen2_composite_picture(sna, src, &tmp->base.src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index b236761..e798096 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2194,7 +2194,7 @@ gen3_init_linear(struct sna *sna,
 	op->u.gen3.constants[n++] = 0;
 
 	if (!gen3_gradient_setup(sna, picture, channel, ox, oy))
-		return 0;
+		return -1;
 
 	channel->u.gen3.type = SHADER_LINEAR;
 	op->u.gen3.num_constants = n;
@@ -2250,7 +2250,7 @@ gen3_init_radial(struct sna *sna,
 	}
 
 	if (!gen3_gradient_setup(sna, picture, channel, ox, oy))
-		return 0;
+		return -1;
 
 	channel->u.gen3.type = SHADER_RADIAL;
 	op->u.gen3.num_constants = n;
@@ -2285,7 +2285,8 @@ gen3_composite_picture(struct sna *sna,
 		       struct sna_composite_channel *channel,
 		       int16_t x, int16_t y,
 		       int16_t w, int16_t h,
-		       int16_t dst_x, int16_t dst_y)
+		       int16_t dst_x, int16_t dst_y,
+		       bool precise)
 {
 	PixmapPtr pixmap;
 	uint32_t color;
@@ -2298,7 +2299,7 @@ gen3_composite_picture(struct sna *sna,
 
 	if (picture->pDrawable == NULL) {
 		SourcePict *source = picture->pSourcePict;
-		int ret = 0;
+		int ret = -1;
 
 		switch (source->type) {
 		case SourcePictTypeSolidFill:
@@ -2316,9 +2317,14 @@ gen3_composite_picture(struct sna *sna,
 			break;
 		}
 
-		if (ret == 0)
-			ret = sna_render_picture_fixup(sna, picture, channel,
-						       x, y, w, h, dst_x, dst_y);
+		if (ret == -1) {
+			if (!precise)
+				ret = sna_render_picture_approximate_gradient(sna, picture, channel,
+									      x, y, w, h, dst_x, dst_y);
+			if (ret == -1)
+				ret = sna_render_picture_fixup(sna, picture, channel,
+							       x, y, w, h, dst_x, dst_y);
+		}
 		return ret;
 	}
 
@@ -2815,7 +2821,8 @@ gen3_render_composite(struct sna *sna,
 	switch (gen3_composite_picture(sna, src, tmp, &tmp->src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
@@ -2840,7 +2847,8 @@ gen3_render_composite(struct sna *sna,
 			switch (gen3_composite_picture(sna, mask, tmp, &tmp->mask,
 						       mask_x, mask_y,
 						       width,  height,
-						       dst_x,  dst_y)) {
+						       dst_x,  dst_y,
+						       dst->polyMode == PolyModePrecise)) {
 			case -1:
 				goto cleanup_src;
 			case 0:
@@ -3379,7 +3387,8 @@ gen3_render_composite_spans(struct sna *sna,
 	switch (gen3_composite_picture(sna, src, &tmp->base, &tmp->base.src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index def5d19..2e78a92 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1957,7 +1957,8 @@ gen4_composite_picture(struct sna *sna,
 		       struct sna_composite_channel *channel,
 		       int x, int y,
 		       int w, int h,
-		       int dst_x, int dst_y)
+		       int dst_x, int dst_y,
+		       bool precise)
 {
 	PixmapPtr pixmap;
 	uint32_t color;
@@ -1973,6 +1974,8 @@ gen4_composite_picture(struct sna *sna,
 		return gen4_composite_solid_init(sna, channel, color);
 
 	if (picture->pDrawable == NULL) {
+		int ret;
+
 		if (picture->pSourcePict->type == SourcePictTypeLinear)
 			return gen4_composite_linear_init(sna, picture, channel,
 							  x, y,
@@ -1980,8 +1983,14 @@ gen4_composite_picture(struct sna *sna,
 							  dst_x, dst_y);
 
 		DBG(("%s -- fixup, gradient\n", __FUNCTION__));
-		return sna_render_picture_fixup(sna, picture, channel,
-						x, y, w, h, dst_x, dst_y);
+		ret = -1;
+		if (!precise)
+			ret = sna_render_picture_approximate_gradient(sna, picture, channel,
+								      x, y, w, h, dst_x, dst_y);
+		if (ret == -1)
+			ret = sna_render_picture_fixup(sna, picture, channel,
+						       x, y, w, h, dst_x, dst_y);
+		return ret;
 	}
 
 	if (picture->alphaMap) {
@@ -2404,7 +2413,8 @@ gen4_render_composite(struct sna *sna,
 	switch (gen4_composite_picture(sna, src, &tmp->src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		DBG(("%s: failed to prepare source\n", __FUNCTION__));
 		goto cleanup_dst;
@@ -2449,7 +2459,8 @@ gen4_render_composite(struct sna *sna,
 			switch (gen4_composite_picture(sna, mask, &tmp->mask,
 						       msk_x, msk_y,
 						       width, height,
-						       dst_x, dst_y)) {
+						       dst_x, dst_y,
+						       dst->polyMode == PolyModePrecise)) {
 			case -1:
 				DBG(("%s: failed to prepare mask\n", __FUNCTION__));
 				goto cleanup_src;
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 565d22a..c27accd 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1990,7 +1990,8 @@ gen5_composite_picture(struct sna *sna,
 		       struct sna_composite_channel *channel,
 		       int x, int y,
 		       int w, int h,
-		       int dst_x, int dst_y)
+		       int dst_x, int dst_y,
+		       bool precise)
 {
 	PixmapPtr pixmap;
 	uint32_t color;
@@ -2006,6 +2007,8 @@ gen5_composite_picture(struct sna *sna,
 		return gen5_composite_solid_init(sna, channel, color);
 
 	if (picture->pDrawable == NULL) {
+		int ret;
+
 		if (picture->pSourcePict->type == SourcePictTypeLinear)
 			return gen5_composite_linear_init(sna, picture, channel,
 							  x, y,
@@ -2013,8 +2016,14 @@ gen5_composite_picture(struct sna *sna,
 							  dst_x, dst_y);
 
 		DBG(("%s -- fixup, gradient\n", __FUNCTION__));
-		return sna_render_picture_fixup(sna, picture, channel,
-						x, y, w, h, dst_x, dst_y);
+		ret = -1;
+		if (!precise)
+			ret = sna_render_picture_approximate_gradient(sna, picture, channel,
+								      x, y, w, h, dst_x, dst_y);
+		if (ret == -1)
+			ret = sna_render_picture_fixup(sna, picture, channel,
+						       x, y, w, h, dst_x, dst_y);
+		return ret;
 	}
 
 	if (picture->alphaMap) {
@@ -2444,7 +2453,8 @@ gen5_render_composite(struct sna *sna,
 	switch (gen5_composite_picture(sna, src, &tmp->src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		DBG(("%s: failed to prepare source picture\n", __FUNCTION__));
 		goto cleanup_dst;
@@ -2488,7 +2498,8 @@ gen5_render_composite(struct sna *sna,
 			switch (gen5_composite_picture(sna, mask, &tmp->mask,
 						       msk_x, msk_y,
 						       width, height,
-						       dst_x, dst_y)) {
+						       dst_x, dst_y,
+						       dst->polyMode == PolyModePrecise)) {
 			case -1:
 				DBG(("%s: failed to prepare mask picture\n", __FUNCTION__));
 				goto cleanup_src;
@@ -2800,7 +2811,8 @@ gen5_render_composite_spans(struct sna *sna,
 	switch (gen5_composite_picture(sna, src, &tmp->base.src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index fde0776..6f1b55a 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2165,7 +2165,8 @@ gen6_composite_picture(struct sna *sna,
 		       struct sna_composite_channel *channel,
 		       int x, int y,
 		       int w, int h,
-		       int dst_x, int dst_y)
+		       int dst_x, int dst_y,
+		       bool precise)
 {
 	PixmapPtr pixmap;
 	uint32_t color;
@@ -2181,6 +2182,8 @@ gen6_composite_picture(struct sna *sna,
 		return gen6_composite_solid_init(sna, channel, color);
 
 	if (picture->pDrawable == NULL) {
+		int ret;
+
 		if (picture->pSourcePict->type == SourcePictTypeLinear)
 			return gen6_composite_linear_init(sna, picture, channel,
 							  x, y,
@@ -2188,8 +2191,14 @@ gen6_composite_picture(struct sna *sna,
 							  dst_x, dst_y);
 
 		DBG(("%s -- fixup, gradient\n", __FUNCTION__));
-		return sna_render_picture_fixup(sna, picture, channel,
-						x, y, w, h, dst_x, dst_y);
+		ret = -1;
+		if (!precise)
+			ret = sna_render_picture_approximate_gradient(sna, picture, channel,
+								      x, y, w, h, dst_x, dst_y);
+		if (ret == -1)
+			ret = sna_render_picture_fixup(sna, picture, channel,
+						       x, y, w, h, dst_x, dst_y);
+		return ret;
 	}
 
 	if (picture->alphaMap) {
@@ -2646,7 +2655,8 @@ gen6_render_composite(struct sna *sna,
 	switch (gen6_composite_picture(sna, src, &tmp->src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
@@ -2702,7 +2712,8 @@ gen6_render_composite(struct sna *sna,
 			switch (gen6_composite_picture(sna, mask, &tmp->mask,
 						       msk_x, msk_y,
 						       width, height,
-						       dst_x, dst_y)) {
+						       dst_x, dst_y,
+						       dst->polyMode == PolyModePrecise)) {
 			case -1:
 				goto cleanup_src;
 			case 0:
@@ -3089,7 +3100,8 @@ gen6_render_composite_spans(struct sna *sna,
 	switch (gen6_composite_picture(sna, src, &tmp->base.src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 36ea8a1..1491167 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2270,7 +2270,8 @@ gen7_composite_picture(struct sna *sna,
 		       struct sna_composite_channel *channel,
 		       int x, int y,
 		       int w, int h,
-		       int dst_x, int dst_y)
+		       int dst_x, int dst_y,
+		       bool precise)
 {
 	PixmapPtr pixmap;
 	uint32_t color;
@@ -2286,6 +2287,8 @@ gen7_composite_picture(struct sna *sna,
 		return gen7_composite_solid_init(sna, channel, color);
 
 	if (picture->pDrawable == NULL) {
+		int ret;
+
 		if (picture->pSourcePict->type == SourcePictTypeLinear)
 			return gen7_composite_linear_init(sna, picture, channel,
 							  x, y,
@@ -2293,8 +2296,14 @@ gen7_composite_picture(struct sna *sna,
 							  dst_x, dst_y);
 
 		DBG(("%s -- fixup, gradient\n", __FUNCTION__));
-		return sna_render_picture_fixup(sna, picture, channel,
-						x, y, w, h, dst_x, dst_y);
+		ret = -1;
+		if (!precise)
+			ret = sna_render_picture_approximate_gradient(sna, picture, channel,
+								      x, y, w, h, dst_x, dst_y);
+		if (ret == -1)
+			ret = sna_render_picture_fixup(sna, picture, channel,
+						       x, y, w, h, dst_x, dst_y);
+		return ret;
 	}
 
 	if (picture->alphaMap) {
@@ -2732,7 +2741,8 @@ gen7_render_composite(struct sna *sna,
 	switch (gen7_composite_picture(sna, src, &tmp->src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
@@ -2788,7 +2798,8 @@ gen7_render_composite(struct sna *sna,
 			switch (gen7_composite_picture(sna, mask, &tmp->mask,
 						       msk_x, msk_y,
 						       width, height,
-						       dst_x, dst_y)) {
+						       dst_x, dst_y,
+						       dst->polyMode == PolyModePrecise)) {
 			case -1:
 				goto cleanup_src;
 			case 0:
@@ -3185,7 +3196,8 @@ gen7_render_composite_spans(struct sna *sna,
 	switch (gen7_composite_picture(sna, src, &tmp->base.src,
 				       src_x, src_y,
 				       width, height,
-				       dst_x, dst_y)) {
+				       dst_x, dst_y,
+				       dst->polyMode == PolyModePrecise)) {
 	case -1:
 		goto cleanup_dst;
 	case 0:
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 542cdb9..d774a34 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1369,6 +1369,92 @@ sna_render_picture_flatten(struct sna *sna,
 }
 
 int
+sna_render_picture_approximate_gradient(struct sna *sna,
+					PicturePtr picture,
+					struct sna_composite_channel *channel,
+					int16_t x, int16_t y,
+					int16_t w, int16_t h,
+					int16_t dst_x, int16_t dst_y)
+{
+	pixman_image_t *dst, *src;
+	pixman_transform_t t;
+	int w2 = w/2, h2 = h/2;
+	int dx, dy;
+	void *ptr;
+
+#if NO_FIXUP
+	return -1;
+#endif
+
+	DBG(("%s: (%d, %d)x(%d, %d)\n", __FUNCTION__, x, y, w, h));
+
+	if (w2 == 0 || h2 == 0) {
+		DBG(("%s: fallback - unknown bounds\n", __FUNCTION__));
+		return -1;
+	}
+	if (w2 > sna->render.max_3d_size || h2 > sna->render.max_3d_size) {
+		DBG(("%s: fallback - too large (%dx%d)\n", __FUNCTION__, w, h));
+		return -1;
+	}
+
+	channel->pict_format = PIXMAN_a8r8g8b8;
+	channel->bo = kgem_create_buffer_2d(&sna->kgem,
+					    w2, h2, 32,
+					    KGEM_BUFFER_WRITE_INPLACE,
+					    &ptr);
+	if (!channel->bo) {
+		DBG(("%s: failed to create upload buffer, using clear\n",
+		     __FUNCTION__));
+		return 0;
+	}
+
+	dst = pixman_image_create_bits(PIXMAN_a8r8g8b8,
+				       w2, h2, ptr, channel->bo->pitch);
+	if (!dst) {
+		kgem_bo_destroy(&sna->kgem, channel->bo);
+		return 0;
+	}
+
+	src = image_from_pict(picture, FALSE, &dx, &dy);
+	if (src == NULL) {
+		pixman_image_unref(dst);
+		kgem_bo_destroy(&sna->kgem, channel->bo);
+		return 0;
+	}
+
+	memset(&t, 0, sizeof(t));
+	t.matrix[0][0] = (w << 16) / w2;
+	t.matrix[1][1] = (h << 16) / h2;
+	t.matrix[2][2] = 1 << 16;
+	if (picture->transform)
+		pixman_transform_multiply(&t, picture->transform, &t);
+	pixman_image_set_transform(src, &t);
+
+	pixman_image_composite(PictOpSrc, src, NULL, dst,
+			       x + dx, y + dy,
+			       0, 0,
+			       0, 0,
+			       w2, h2);
+	free_pixman_pict(picture, src);
+	pixman_image_unref(dst);
+
+	channel->width  = w2;
+	channel->height = h2;
+
+	channel->filter = PictFilterNearest;
+	channel->repeat = RepeatNone;
+	channel->is_affine = TRUE;
+
+	channel->scale[0] = 1.f/w;
+	channel->scale[1] = 1.f/h;
+	channel->offset[0] = -dst_x;
+	channel->offset[1] = -dst_y;
+	channel->transform = NULL;
+
+	return 1;
+}
+
+int
 sna_render_picture_fixup(struct sna *sna,
 			 PicturePtr picture,
 			 struct sna_composite_channel *channel,
diff --git a/src/sna/sna_render.h b/src/sna/sna_render.h
index 8d3d9e4..a83f78e 100644
--- a/src/sna/sna_render.h
+++ b/src/sna/sna_render.h
@@ -615,6 +615,14 @@ sna_render_picture_extract(struct sna *sna,
 			   int16_t dst_x, int16_t dst_y);
 
 int
+sna_render_picture_approximate_gradient(struct sna *sna,
+					PicturePtr picture,
+					struct sna_composite_channel *channel,
+					int16_t x, int16_t y,
+					int16_t w, int16_t h,
+					int16_t dst_x, int16_t dst_y);
+
+int
 sna_render_picture_fixup(struct sna *sna,
 			 PicturePtr picture,
 			 struct sna_composite_channel *channel,


More information about the xorg-commit mailing list