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_composite.c src/sna/sna_glyphs.c src/sna/sna_render.c src/sna/sna_render_inline.h src/sna/sna_trapezoids.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Dec 22 09:36:50 PST 2011


 src/sna/gen2_render.c       |   14 +++
 src/sna/gen3_render.c       |   14 +++
 src/sna/gen4_render.c       |   14 +++
 src/sna/gen5_render.c       |   14 +++
 src/sna/gen6_render.c       |   14 +++
 src/sna/gen7_render.c       |   14 +++
 src/sna/sna_accel.c         |   50 +++++++++---
 src/sna/sna_composite.c     |   16 +++
 src/sna/sna_glyphs.c        |    4 
 src/sna/sna_render.c        |  181 ++++++++++++++++++++++++++++++++++++++++++++
 src/sna/sna_render_inline.h |   10 ++
 src/sna/sna_trapezoids.c    |    9 --
 12 files changed, 327 insertions(+), 27 deletions(-)

New commits:
commit 609e1d9da282323ab7abc1baad4d3f24ac55588f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 22 15:54:39 2011 +0000

    sna: Bump the inactivity timeout
    
    With the goal of removing inactive pixmap froms the GPU after 5 minutes
    of idleness.
    
    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 8756fab..8a2ff9a 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -8970,8 +8970,8 @@ static Bool sna_accel_do_inactive(struct sna *sna)
 	if (sna->timer[INACTIVE_TIMER] == -1)
 		return FALSE;
 
-	/* Periodic expiration after every 60s. */
-	to.it_interval.tv_sec = 60;
+	/* Periodic expiration after every 2 minutes. */
+	to.it_interval.tv_sec = 120;
 	to.it_interval.tv_nsec = 0;
 	to.it_value = to.it_interval;
 	timerfd_settime(sna->timer[INACTIVE_TIMER], 0, &to, NULL);
commit 62602209e54c3568795122ee1c902c3b81985303
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 22 14:20:20 2011 +0000

    sna: discard damage-all even for width|height==0 operations
    
    Even if we don't know the extents of the render operation, if the entire
    pixmap is damaged we can still reduce the damage tracking.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index 758833e..58eced0 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -139,7 +139,15 @@ sna_render_reduce_damage(struct sna_composite_op *op,
 {
 	BoxRec r;
 
-	if (width == 0 || height == 0 || op->damage == NULL)
+	if (op->damage == NULL || *op->damage == NULL)
+		return;
+
+	if ((*op->damage)->mode == DAMAGE_ALL) {
+		op->damage = NULL;
+		return;
+	}
+
+	if (width == 0 || height == 0)
 		return;
 
 	r.x1 = dst_x + op->dst.x;
commit f68a99a55e1e63d7e76a13a7b77b4bb3f7802b9e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 22 15:04:22 2011 +0000

    sna: Mark fresh GPU only bo as being all damaged
    
    Presume that we will not fallback and so treat a GPU only bo (one that
    is initially created on the GPU) as being all-damaged. This makes future
    operations cheaper as the damage tracking overhead is much reduced, and
    the cost of the first readback will mainly be in the synchronisation
    overhead.
    
    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 27fd354..8756fab 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1347,6 +1347,18 @@ sna_pixmap_move_to_gpu(PixmapPtr pixmap)
 			assert(list_is_empty(&priv->list));
 			return NULL;
 		}
+
+		if (priv->cpu_damage == NULL) {
+			/* Presume that we will only ever write to the GPU
+			 * bo. Readbacks are expensive but fairly constant
+			 * in cost for all sizes i.e. it is the act of
+			 * synchronisation that takes the most time. This is
+			 * mitigated by avoiding fallbacks in the first place.
+			 */
+			sna_damage_all(&priv->gpu_damage,
+				       pixmap->drawable.width,
+				       pixmap->drawable.height);
+		}
 	}
 
 	if (priv->cpu_damage == NULL)
commit 1f2cd536bc712843233de3f5c50802c388d63c72
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 22 14:30:04 2011 +0000

    sna: Reduce damage after complete solid fills
    
    RenderFillRectangles is often used to initially clear a pixmap after
    creation by flooding it with a solid colour, as is PolyRect. We can
    reduce further damage operations by checking for this condition.
    
    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 e899760..27fd354 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -6283,7 +6283,13 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
 						 gc->alu)) {
 				if (damage) {
 					assert_pixmap_contains_box(pixmap, &r);
-					sna_damage_add_box(damage, &r);
+					if (r.x2 - r.x1 == pixmap->drawable.width &&
+					    r.y2 - r.y1 == pixmap->drawable.height)
+						sna_damage_all(damage,
+							       pixmap->drawable.width,
+							       pixmap->drawable.height);
+					else
+						sna_damage_add_box(damage, &r);
 				}
 			} else
 				success = false;
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index 7adbbfb..98bf871 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -742,7 +742,17 @@ sna_composite_rectangles(CARD8		 op,
 	}
 
 	assert_pixmap_contains_box(pixmap, RegionExtents(&region));
-	sna_damage_add(&priv->gpu_damage, &region);
+
+	/* Clearing a pixmap after creation is a common operation, so take
+	 * advantage and reduce further damage operations.
+	 */
+	if (region.data == NULL &&
+	    region.extents.x2 - region.extents.x1 == pixmap->drawable.width &&
+	    region.extents.y2 - region.extents.y1 == pixmap->drawable.height)
+		sna_damage_all(&priv->gpu_damage,
+			       pixmap->drawable.width, pixmap->drawable.height);
+	else
+		sna_damage_add(&priv->gpu_damage, &region);
 
 	goto done;
 
@@ -759,7 +769,7 @@ fallback:
 	    !sna_drawable_move_to_cpu(dst->alphaMap->pDrawable, error))
 		goto done;
 
-	if (op == PictOpSrc || op == PictOpClear) {
+	if (op <= PictOpSrc) {
 		int nbox = REGION_NUM_RECTS(&region);
 		BoxPtr box = REGION_RECTS(&region);
 		uint32_t pixel;
commit 7a6a2c5d4cc98da76c73152cb7eafcbdb0c088ec
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 22 13:24:07 2011 +0000

    sna: Setup the pixmap correctly in order to attach our private
    
    During creation of sna_pixmap we validate that we can use a GPU bo with
    the target pixmap. This fails if we pass in a raw pixmap header, so
    make sure the scratch pixmap is fully initialised first.
    
    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 b3fc05b..e899760 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -508,9 +508,14 @@ sna_pixmap_create_scratch(ScreenPtr screen,
 		sna->freed_pixmap = NULL;
 
 		pixmap->usage_hint = CREATE_PIXMAP_USAGE_SCRATCH;
-		pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
 		pixmap->refcnt = 1;
 
+		pixmap->drawable.width = width;
+		pixmap->drawable.height = height;
+		pixmap->drawable.depth = depth;
+		pixmap->drawable.bitsPerPixel = bpp;
+		pixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
 		priv = _sna_pixmap_reset(pixmap);
 	} else {
 		pixmap = create_pixmap(sna, screen, 0, 0, depth,
@@ -518,6 +523,11 @@ sna_pixmap_create_scratch(ScreenPtr screen,
 		if (pixmap == NullPixmap)
 			return NullPixmap;
 
+		pixmap->drawable.width = width;
+		pixmap->drawable.height = height;
+		pixmap->drawable.depth = depth;
+		pixmap->drawable.bitsPerPixel = bpp;
+
 		priv = _sna_pixmap_attach(sna, pixmap);
 		if (!priv) {
 			fbDestroyPixmap(pixmap);
@@ -525,6 +535,9 @@ sna_pixmap_create_scratch(ScreenPtr screen,
 		}
 	}
 
+	pixmap->devKind = PixmapBytePad(width, depth);
+	pixmap->devPrivate.ptr = NULL;
+
 	priv->gpu_bo = kgem_create_2d(&sna->kgem,
 				      width, height, bpp, tiling,
 				      0);
@@ -537,12 +550,6 @@ sna_pixmap_create_scratch(ScreenPtr screen,
 	priv->header = true;
 	sna_damage_all(&priv->gpu_damage, width, height);
 
-	pixmap->drawable.width = width;
-	pixmap->drawable.height = height;
-	pixmap->drawable.depth = depth;
-	pixmap->drawable.bitsPerPixel = bpp;
-	pixmap->devKind = PixmapBytePad(width, depth);
-	pixmap->devPrivate.ptr = NULL;
 
 	return pixmap;
 }
commit f621b3de841f6037d387ca1439a0abe12ef29811
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 22 11:19:45 2011 +0000

    sna: flatten source alphamaps
    
    Replace the source picture+alpha with a bo that contains the RGB
    channels from source and A from the alpha map.
    
    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 53accbd..519ba18 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1155,6 +1155,12 @@ gen2_composite_picture(struct sna *sna,
 						x, y, w, h, dst_x, dst_y);
 	}
 
+	if (picture->alphaMap) {
+		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
+		return sna_render_picture_fixup(sna, picture, channel,
+						x, y, w, h, dst_x, dst_y);
+	}
+
 	if (!gen2_check_repeat(picture)) {
 		DBG(("%s -- fallback, unhandled repeat %d\n",
 		     __FUNCTION__, picture->repeat));
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 1dec2b3..12eebaa 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2099,6 +2099,12 @@ gen3_composite_picture(struct sna *sna,
 		return ret;
 	}
 
+	if (picture->alphaMap) {
+		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
+		return sna_render_picture_fixup(sna, picture, channel,
+						x, y, w, h, dst_x, dst_y);
+	}
+
 	if (sna_picture_is_solid(picture, &color))
 		return gen3_init_solid(channel, color);
 
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 150b7c8..6ccddd2 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1745,6 +1745,12 @@ gen4_composite_picture(struct sna *sna,
 						x, y, w, h, dst_x, dst_y);
 	}
 
+	if (picture->alphaMap) {
+		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
+		return sna_render_picture_fixup(sna, picture, channel,
+						x, y, w, h, dst_x, dst_y);
+	}
+
 	if (!gen4_check_repeat(picture)) {
 		DBG(("%s: unknown repeat mode fixup\n", __FUNCTION__));
 		return sna_render_picture_fixup(sna, picture, channel,
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index e1117cc..180b561 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1785,6 +1785,12 @@ gen5_composite_picture(struct sna *sna,
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
 
+	if (picture->alphaMap) {
+		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
+		return sna_render_picture_fixup(sna, picture, channel,
+						x, y, w, h, dst_x, dst_y);
+	}
+
 	if (!gen5_check_repeat(picture))
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 7d48137..8e7ea15 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -1962,6 +1962,12 @@ gen6_composite_picture(struct sna *sna,
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
 
+	if (picture->alphaMap) {
+		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
+		return sna_render_picture_fixup(sna, picture, channel,
+						x, y, w, h, dst_x, dst_y);
+	}
+
 	if (!gen6_check_repeat(picture))
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 885a5dc..58647f7 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2075,6 +2075,12 @@ gen7_composite_picture(struct sna *sna,
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
 
+	if (picture->alphaMap) {
+		DBG(("%s -- fallback, alphamap\n", __FUNCTION__));
+		return sna_render_picture_fixup(sna, picture, channel,
+						x, y, w, h, dst_x, dst_y);
+	}
+
 	if (!gen7_check_repeat(picture))
 		return sna_render_picture_fixup(sna, picture, channel,
 						x, y, w, h, dst_x, dst_y);
diff --git a/src/sna/sna_composite.c b/src/sna/sna_composite.c
index fcc0070..7adbbfb 100644
--- a/src/sna/sna_composite.c
+++ b/src/sna/sna_composite.c
@@ -437,7 +437,7 @@ sna_composite(CARD8 op,
 		goto fallback;
 	}
 
-	if (dst->alphaMap || src->alphaMap || (mask && mask->alphaMap)) {
+	if (dst->alphaMap) {
 		DBG(("%s: fallback due to unhandled alpha-map\n", __FUNCTION__));
 		goto fallback;
 	}
diff --git a/src/sna/sna_glyphs.c b/src/sna/sna_glyphs.c
index 4fd4752..811b866 100644
--- a/src/sna/sna_glyphs.c
+++ b/src/sna/sna_glyphs.c
@@ -1225,8 +1225,8 @@ sna_glyphs(CARD8 op,
 		goto fallback;
 	}
 
-	if (dst->alphaMap || src->alphaMap) {
-		DBG(("%s: fallback -- alpha maps\n", __FUNCTION__));
+	if (dst->alphaMap) {
+		DBG(("%s: fallback -- dst alpha map\n", __FUNCTION__));
 		goto fallback;
 	}
 
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 72b3f78..89d1d81 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -1014,6 +1014,73 @@ sna_render_picture_convolve(struct sna *sna,
 	return 1;
 }
 
+static int
+sna_render_picture_flatten(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)
+{
+	ScreenPtr screen = picture->pDrawable->pScreen;
+	PixmapPtr pixmap;
+	PicturePtr tmp, alpha;
+	int old_format, error;
+
+	assert(picture->pDrawable);
+	assert(picture->alphaMap);
+	assert(w <= sna->render.max_3d_size && h <= sna->render.max_3d_size);
+
+	/* XXX shortcut a8? */
+
+	pixmap = screen->CreatePixmap(screen, w, h, 32, SNA_CREATE_SCRATCH);
+	if (pixmap == NullPixmap)
+		return 0;
+
+	tmp = CreatePicture(0, &pixmap->drawable,
+			    PictureMatchFormat(screen, 32, PICT_a8r8g8b8),
+			    0, NULL, serverClient, &error);
+	screen->DestroyPixmap(pixmap);
+	if (tmp == NULL)
+		return 0;
+
+	old_format = picture->format;
+	picture->format = PICT_FORMAT(PICT_FORMAT_BPP(picture->format),
+				      PICT_FORMAT_TYPE(picture->format),
+				      0,
+				      PICT_FORMAT_R(picture->format),
+				      PICT_FORMAT_G(picture->format),
+				      PICT_FORMAT_B(picture->format));
+
+	alpha = picture->alphaMap;
+	picture->alphaMap = NULL;
+
+	sna_composite(PictOpSrc, picture, alpha, tmp,
+		      x, y,
+		      x + picture->alphaOrigin.x, y + picture->alphaOrigin.y,
+		      0, 0,
+		      w, h);
+
+	picture->format = old_format;
+	picture->alphaMap = alpha;
+
+	channel->height = h;
+	channel->width  = w;
+	channel->filter = PictFilterNearest;
+	channel->repeat = RepeatNone;
+	channel->pict_format = PIXMAN_a8r8g8b8;
+	channel->is_affine = TRUE;
+	channel->transform = NULL;
+	channel->scale[0] = 1.f / w;
+	channel->scale[1] = 1.f / h;
+	channel->offset[0] = -dst_x;
+	channel->offset[1] = -dst_y;
+	channel->bo = kgem_bo_reference(sna_pixmap_get_bo(pixmap));
+	FreePicture(tmp, 0);
+
+	return 1;
+}
+
 int
 sna_render_picture_fixup(struct sna *sna,
 			 PicturePtr picture,
@@ -1042,6 +1109,16 @@ sna_render_picture_fixup(struct sna *sna,
 		return -1;
 	}
 
+	if (picture->alphaMap) {
+		DBG(("%s: alphamap\n", __FUNCTION__));
+		if ((is_gpu(picture->pDrawable) || is_gpu(picture->alphaMap->pDrawable))) {
+			return sna_render_picture_flatten(sna, picture, channel,
+							  x, y, w, y, dst_x, dst_y);
+		}
+
+		goto do_fixup;
+	}
+
 	if (picture->filter == PictFilterConvolution) {
 		DBG(("%s: convolution\n", __FUNCTION__));
 		if (picture->pDrawable && is_gpu(picture->pDrawable)) {
diff --git a/src/sna/sna_trapezoids.c b/src/sna/sna_trapezoids.c
index 287f883..3837532 100644
--- a/src/sna/sna_trapezoids.c
+++ b/src/sna/sna_trapezoids.c
@@ -3094,8 +3094,8 @@ trapezoid_span_inplace(CARD8 op, PicturePtr src, PicturePtr dst,
 		     __FUNCTION__));
 		return false;
 	}
-	if (dst->alphaMap || src->alphaMap) {
-		DBG(("%s: fallback -- alphamaps\n",
+	if (dst->alphaMap) {
+		DBG(("%s: fallback -- dst alphamap\n",
 		     __FUNCTION__));
 		return false;
 	}
@@ -3374,9 +3374,8 @@ sna_composite_trapezoids(CARD8 op,
 		goto fallback;
 	}
 
-	if (dst->alphaMap || src->alphaMap) {
-		DBG(("%s: fallback -- alpha maps=(dst=%p, src=%p)\n",
-		     __FUNCTION__, dst->alphaMap, src->alphaMap));
+	if (dst->alphaMap) {
+		DBG(("%s: fallback -- dst alpha map\n", __FUNCTION__));
 		goto fallback;
 	}
 
commit 6c08eb4d6f8789e692ef018e007d1ae97a57c25f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Dec 22 11:42:39 2011 +0000

    sna/gen2+: Prefer to use the CPU if we have a source alphamap and CPU pictures
    
    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 d10f03e..53accbd 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -1304,9 +1304,15 @@ is_gradient(PicturePtr picture)
 }
 
 static bool
+has_alphamap(PicturePtr p)
+{
+	return p->alphaMap != NULL;
+}
+
+static bool
 source_fallback(PicturePtr p)
 {
-	return is_gradient(p) || !gen2_check_filter(p) || !gen2_check_repeat(p);
+	return has_alphamap(p) || is_gradient(p) || !gen2_check_filter(p) || !gen2_check_repeat(p);
 }
 
 static bool
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 4ada863..1dec2b3 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -2297,9 +2297,15 @@ is_solid(PicturePtr picture)
 }
 
 static bool
+has_alphamap(PicturePtr p)
+{
+	return p->alphaMap != NULL;
+}
+
+static bool
 source_fallback(PicturePtr p)
 {
-	return !gen3_check_filter(p->filter) || !gen3_check_repeat(p);
+	return has_alphamap(p) || !gen3_check_filter(p->filter) || !gen3_check_repeat(p);
 }
 
 static bool
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index aec5ca0..150b7c8 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1911,9 +1911,15 @@ is_gradient(PicturePtr picture)
 }
 
 static bool
+has_alphamap(PicturePtr p)
+{
+	return p->alphaMap != NULL;
+}
+
+static bool
 source_fallback(PicturePtr p)
 {
-	return is_gradient(p) || !gen4_check_filter(p) || !gen4_check_repeat(p);
+	return has_alphamap(p) || is_gradient(p) || !gen4_check_filter(p) || !gen4_check_repeat(p);
 }
 
 static bool
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 6d89ca3..e1117cc 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1953,9 +1953,15 @@ is_gradient(PicturePtr picture)
 }
 
 static bool
+has_alphamap(PicturePtr p)
+{
+	return p->alphaMap != NULL;
+}
+
+static bool
 source_fallback(PicturePtr p)
 {
-	return is_gradient(p) || !gen5_check_filter(p) || !gen5_check_repeat(p);
+	return has_alphamap(p) || is_gradient(p) || !gen5_check_filter(p) || !gen5_check_repeat(p);
 }
 
 static bool
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index c276f7e..7d48137 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2128,9 +2128,15 @@ is_gradient(PicturePtr picture)
 }
 
 static bool
+has_alphamap(PicturePtr p)
+{
+	return p->alphaMap != NULL;
+}
+
+static bool
 source_fallback(PicturePtr p)
 {
-	return is_gradient(p) || !gen6_check_filter(p) || !gen6_check_repeat(p);
+	return has_alphamap(p) || is_gradient(p) || !gen6_check_filter(p) || !gen6_check_repeat(p);
 }
 
 static bool
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index dc97d18..885a5dc 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2241,9 +2241,15 @@ is_gradient(PicturePtr picture)
 }
 
 static bool
+has_alphamap(PicturePtr p)
+{
+	return p->alphaMap != NULL;
+}
+
+static bool
 source_fallback(PicturePtr p)
 {
-	return is_gradient(p) || !gen7_check_filter(p) || !gen7_check_repeat(p);
+	return has_alphamap(p) || is_gradient(p) || !gen7_check_filter(p) || !gen7_check_repeat(p);
 }
 
 static bool
commit 354dc3c65b9cb86885b6927ee2b80cd2ee6a82ff
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Dec 21 21:35:06 2011 +0000

    sna: Avoid fallbacks for convolutions by rendering the convolved texture
    
    If we have no shader support for generic convolutions, we currently
    create the convolved texture using pixman. A multipass accumulation
    algorithm can be implemented on top of CompositePicture, so try it!
    
    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 33a75c1..b3fc05b 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -491,6 +491,11 @@ sna_pixmap_create_scratch(ScreenPtr screen,
 	if (tiling == I915_TILING_Y && !sna->have_render)
 		tiling = I915_TILING_X;
 
+	  if (tiling == I915_TILING_Y &&
+	      (width > sna->render.max_3d_size ||
+	       height > sna->render.max_3d_size))
+		  tiling = I915_TILING_X;
+
 	bpp = BitsPerPixel(depth);
 	tiling = kgem_choose_tiling(&sna->kgem, tiling, width, height, bpp);
 	if (!kgem_can_create_2d(&sna->kgem, width, height, bpp, tiling))
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 341cf2c..72b3f78 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -921,6 +921,99 @@ sna_render_picture_extract(struct sna *sna,
 	return 1;
 }
 
+static int
+sna_render_picture_convolve(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)
+{
+	ScreenPtr screen = picture->pDrawable->pScreen;
+	PixmapPtr pixmap;
+	PicturePtr tmp;
+	pixman_fixed_t *params = picture->filter_params;
+	int x_off = (params[0] - pixman_fixed_1) >> 1;
+	int y_off = (params[1] - pixman_fixed_1) >> 1;
+	int cw = pixman_fixed_to_int(params[0]);
+	int ch = pixman_fixed_to_int(params[1]);
+	int i, j, error, depth;
+
+	/* Lame multi-pass accumulation implementation of a general convolution
+	 * that works everywhere.
+	 */
+
+	assert(picture->pDrawable);
+	assert(picture->filter == PictFilterConvolution);
+	assert(w <= sna->render.max_3d_size && h <= sna->render.max_3d_size);
+
+	if (PICT_FORMAT_RGB(picture->format) == 0) {
+		channel->pict_format = PIXMAN_a8;
+		depth = 8;
+	} else {
+		channel->pict_format = PIXMAN_a8r8g8b8;
+		depth = 32;
+	}
+
+	pixmap = screen->CreatePixmap(screen, w, h, depth, SNA_CREATE_SCRATCH);
+	if (pixmap == NullPixmap)
+		return 0;
+
+	tmp = CreatePicture(0, &pixmap->drawable,
+			    PictureMatchFormat(screen, depth, channel->pict_format),
+			    0, NULL, serverClient, &error);
+	screen->DestroyPixmap(pixmap);
+	if (tmp == NULL)
+		return 0;
+
+	if (!sna->render.fill_one(sna, pixmap, sna_pixmap_get_bo(pixmap), 0,
+				  0, 0, w, h, GXclear)) {
+		FreePicture(tmp, 0);
+		return 0;
+	}
+
+	picture->filter = PictFilterBilinear;
+	params += 2;
+	for (j = 0; j < ch; j++) {
+		for (i = 0; i < cw; i++) {
+			xRenderColor color;
+			PicturePtr alpha;
+
+			color.alpha = *params++;
+			color.red = color.green = color.blue = 0;
+
+			if (color.alpha <= 0x00ff)
+				continue;
+
+			alpha = CreateSolidPicture(0, &color, &error);
+			if (alpha) {
+				sna_composite(PictOpAdd, picture, alpha, tmp,
+					      x, y,
+					      0, 0,
+					      x_off-i, y_off-j,
+					      w, h);
+				FreePicture(alpha, 0);
+			}
+		}
+	}
+	picture->filter = PictFilterConvolution;
+
+	channel->height = h;
+	channel->width  = w;
+	channel->filter = PictFilterNearest;
+	channel->repeat = RepeatNone;
+	channel->is_affine = TRUE;
+	channel->transform = NULL;
+	channel->scale[0] = 1.f / w;
+	channel->scale[1] = 1.f / h;
+	channel->offset[0] = -dst_x;
+	channel->offset[1] = -dst_y;
+	channel->bo = kgem_bo_reference(sna_pixmap_get_bo(pixmap));
+	FreePicture(tmp, 0);
+
+	return 1;
+}
+
 int
 sna_render_picture_fixup(struct sna *sna,
 			 PicturePtr picture,
@@ -949,6 +1042,17 @@ sna_render_picture_fixup(struct sna *sna,
 		return -1;
 	}
 
+	if (picture->filter == PictFilterConvolution) {
+		DBG(("%s: convolution\n", __FUNCTION__));
+		if (picture->pDrawable && is_gpu(picture->pDrawable)) {
+			return sna_render_picture_convolve(sna, picture, channel,
+							   x, y, w, y, dst_x, dst_y);
+		}
+
+		goto do_fixup;
+	}
+
+do_fixup:
 	if (PICT_FORMAT_RGB(picture->format) == 0) {
 		pitch = ALIGN(w, 4);
 		channel->pict_format = PIXMAN_a8;


More information about the xorg-commit mailing list