xf86-video-intel: 14 commits - 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_damage.c src/sna/sna_damage.h src/sna/sna_render.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Jan 24 11:30:50 PST 2012


 src/sna/gen3_render.c |   22 +++
 src/sna/gen4_render.c |    1 
 src/sna/gen5_render.c |    1 
 src/sna/gen6_render.c |    1 
 src/sna/gen7_render.c |    1 
 src/sna/kgem.c        |    1 
 src/sna/sna_accel.c   |  279 ++++++++++++++++++++++++++++++++++----------------
 src/sna/sna_damage.c  |   82 ++++++++++++++
 src/sna/sna_damage.h  |   12 ++
 src/sna/sna_render.c  |   12 ++
 10 files changed, 326 insertions(+), 86 deletions(-)

New commits:
commit 5312ee90ad80eda1c6ff72fbef60f77f03094972
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 19:02:56 2012 +0000

    sna: mark the pixmap as no longer clear after rendering video
    
    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 acccf0a..618f694 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3745,6 +3745,7 @@ gen3_render_video(struct sna *sna,
 						  pix_xoff, pix_yoff);
 		}
 	}
+	priv->clear = false;
 
 	return TRUE;
 }
diff --git a/src/sna/gen4_render.c b/src/sna/gen4_render.c
index 5ffd4a7..c1ceb33 100644
--- a/src/sna/gen4_render.c
+++ b/src/sna/gen4_render.c
@@ -1785,6 +1785,7 @@ gen4_render_video(struct sna *sna,
 		}
 		box++;
 	}
+	priv->clear = false;
 
 	gen4_vertex_flush(sna, &tmp);
 	return TRUE;
diff --git a/src/sna/gen5_render.c b/src/sna/gen5_render.c
index 768a5db..6308d10 100644
--- a/src/sna/gen5_render.c
+++ b/src/sna/gen5_render.c
@@ -1816,6 +1816,7 @@ gen5_render_video(struct sna *sna,
 		}
 		box++;
 	}
+	priv->clear = false;
 
 	gen5_vertex_flush(sna);
 	return TRUE;
diff --git a/src/sna/gen6_render.c b/src/sna/gen6_render.c
index 371e999..5cbdd74 100644
--- a/src/sna/gen6_render.c
+++ b/src/sna/gen6_render.c
@@ -2028,6 +2028,7 @@ gen6_render_video(struct sna *sna,
 		}
 		box++;
 	}
+	priv->clear = false;
 
 	gen6_vertex_flush(sna);
 	return TRUE;
diff --git a/src/sna/gen7_render.c b/src/sna/gen7_render.c
index 209d8a0..ee546e1 100644
--- a/src/sna/gen7_render.c
+++ b/src/sna/gen7_render.c
@@ -2094,6 +2094,7 @@ gen7_render_video(struct sna *sna,
 		}
 		box++;
 	}
+	priv->clear = false;
 
 	gen7_vertex_flush(sna);
 	return TRUE;
commit 69d3fc91f4a397f704b9971f97a905626e86eb3c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 18:51:32 2012 +0000

    sna: Set up GC for general FillArc to FillSpans callback
    
    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 cadd1c9..6247fa6 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -9777,6 +9777,7 @@ sna_poly_fill_arc(DrawablePtr draw, GCPtr gc, int n, xArc *arc)
 		uint32_t color;
 
 		get_drawable_deltas(draw, data.pixmap, &data.dx, &data.dy);
+		sna_gc(gc)->priv = &data;
 
 		if (gc_is_solid(gc, &color)) {
 			struct sna_fill_op fill;
@@ -9787,7 +9788,6 @@ sna_poly_fill_arc(DrawablePtr draw, GCPtr gc, int n, xArc *arc)
 				goto fallback;
 
 			data.op = &fill;
-			sna_gc(gc)->priv = &data;
 
 			if ((data.flags & 2) == 0) {
 				if (data.dx | data.dy)
commit 855c45c65a69d34ad32a97a5fc54dd09d40d3e26
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 18:48:17 2012 +0000

    sna: Enable clipping for mi FillSpans gpu callback
    
    The mi routines do not ensure that their output is suitably constrained
    to the clip extents, so we must run it through the clipper.
    
    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 01b44a0..cadd1c9 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -4389,11 +4389,15 @@ sna_fill_spans__gpu(DrawablePtr drawable, GCPtr gc, int n,
 	if (n == 0)
 		return;
 
+	/* The mi routines do not attempt to keep the spans it generates
+	 * within the clip, so we must run them through the clipper.
+	 */
+
 	if (gc_is_solid(gc, &color)) {
 		sna_fill_spans_blt(drawable,
-				   data->bo, data->damage,
+				   data->bo, NULL,
 				   gc, color, n, pt, width, sorted,
-				   &data->region.extents, data->flags & 2);
+				   &data->region.extents, 2);
 	} else {
 		/* Try converting these to a set of rectangles instead */
 		xRectangle *rect;
@@ -4414,16 +4418,14 @@ sna_fill_spans__gpu(DrawablePtr drawable, GCPtr gc, int n,
 
 		if (gc->fillStyle == FillTiled) {
 			sna_poly_fill_rect_tiled_blt(drawable,
-						     data->bo, data->damage,
+						     data->bo, NULL,
 						     gc, n, rect,
-						     &data->region.extents,
-						     data->flags & 2);
+						     &data->region.extents, 2);
 		} else {
 			sna_poly_fill_rect_stippled_blt(drawable,
-							data->bo, data->damage,
+							data->bo, NULL,
 							gc, n, rect,
-							&data->region.extents,
-							data->flags & 2);
+							&data->region.extents, 2);
 		}
 		free (rect);
 	}
commit c3fe42cde70a06a9a9a6190934df5cddb41d2f5f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 18:36:08 2012 +0000

    sna: Don't attempt to create pixmaps for dpeths smaller than 8
    
    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 44912b8..01b44a0 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -668,7 +668,7 @@ static PixmapPtr sna_create_pixmap(ScreenPtr screen,
 	DBG(("%s(%d, %d, %d, usage=%x)\n", __FUNCTION__,
 	     width, height, depth, usage));
 
-	if (wedged(sna) || !sna->have_render)
+	if (depth < 8 || wedged(sna) || !sna->have_render)
 		return create_pixmap(sna, screen,
 				     width, height, depth,
 				     usage);
commit 22bab3cd7d0b2bcedfdd86f198d1ed9a21dd82aa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 18:33:14 2012 +0000

    sna: Handle malloc failures when downsampling
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 56d0014..af81735 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -734,9 +734,19 @@ static int sna_render_picture_downsample(struct sna *sna,
 
 		tmp_dst = CreatePicture(0, &tmp->drawable, format, 0, NULL,
 					serverClient, &error);
+		if (!tmp_dst) {
+			screen->DestroyPixmap(tmp);
+			goto fixup;
+		}
 
 		tmp_src = CreatePicture(0, &pixmap->drawable, format, 0, NULL,
 					serverClient, &error);
+		if (!tmp_src) {
+			FreePicture(tmp_dst, 0);
+			screen->DestroyPixmap(tmp);
+			goto fixup;
+		}
+
 		tmp_src->repeat = true;
 		tmp_src->repeatType = RepeatPad;
 		tmp_src->filter = PictFilterBilinear;
commit 4aef9e6f50cb96c57b7ba345a18e55c97d788192
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 17:23:43 2012 +0000

    sna: Add more damage-is-contained asserts
    
    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 5b90941..44912b8 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -168,9 +168,27 @@ static void _assert_pixmap_contains_box(PixmapPtr pixmap, BoxPtr box, const char
 		assert(0);
 	}
 }
+
+static void _assert_drawable_contains_box(DrawablePtr drawable, const BoxRec *box, const char *function)
+{
+	if (box->x1 < drawable->x ||
+	    box->y1 < drawable->y ||
+	    box->x2 > drawable->x + drawable->width ||
+	    box->y2 > drawable->y + drawable->height)
+	{
+		ErrorF("%s: damage box is beyond the drawable: box=(%d, %d), (%d, %d), drawable=(%d, %d)x(%d, %d)\n",
+		       __FUNCTION__,
+		       box->x1, box->y1, box->x2, box->y2,
+		       drawable->x, drawable->y,
+		       drawable->width, drawable->height);
+		assert(0);
+	}
+}
 #define assert_pixmap_contains_box(p, b) _assert_pixmap_contains_box(p, b, __FUNCTION__)
+#define assert_drawable_contains_box(d, b) _assert_drawable_contains_box(d, b, __FUNCTION__)
 #else
 #define assert_pixmap_contains_box(p, b)
+#define assert_drawable_contains_box(d, b)
 #endif
 
 inline static bool
@@ -1054,10 +1072,10 @@ pixmap_contains_damage(PixmapPtr pixmap, struct sna_damage *damage)
 		return true;
 
 	damage = DAMAGE_PTR(damage);
-	return damage->extents.x2 <= pixmap->drawable.width &&
+	return (damage->extents.x2 <= pixmap->drawable.width &&
 		damage->extents.y2 <= pixmap->drawable.height &&
 		damage->extents.x1 >= 0 &&
-		damage->extents.y1 >= 0;
+		damage->extents.y1 >= 0);
 }
 #endif
 
@@ -1119,6 +1137,8 @@ sna_drawable_move_region_to_cpu(DrawablePtr drawable,
 	     RegionExtents(region)->x2, RegionExtents(region)->y2,
 	     flags));
 
+	assert_pixmap_contains_box(pixmap, &region->extents);
+
 	priv = sna_pixmap(pixmap);
 	if (priv == NULL) {
 		DBG(("%s: not attached to %p\n", __FUNCTION__, pixmap));
@@ -1508,6 +1528,8 @@ sna_pixmap_move_area_to_gpu(PixmapPtr pixmap, BoxPtr box, unsigned int flags)
 
 	DBG(("%s()\n", __FUNCTION__));
 
+	assert_pixmap_contains_box(pixmap, box);
+
 	if (DAMAGE_IS_ALL(priv->gpu_damage))
 		goto done;
 
@@ -1660,6 +1682,8 @@ _sna_drawable_use_gpu_bo(DrawablePtr drawable,
 	BoxRec extents;
 	int16_t dx, dy;
 
+	assert_drawable_contains_box(drawable, box);
+
 	if (priv == NULL) {
 		DBG(("%s: not attached\n", __FUNCTION__));
 		return FALSE;
@@ -1792,6 +1816,8 @@ _sna_drawable_use_cpu_bo(DrawablePtr drawable,
 	BoxRec extents;
 	int16_t dx, dy;
 
+	assert_drawable_contains_box(drawable, box);
+
 	if (priv == NULL || priv->cpu_bo == NULL)
 		return FALSE;
 
commit 16462e551d575bd5a370a8ac8b450ba72fea7d47
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 17:47:22 2012 +0000

    sna: Install CPU handler for PolyLine for miPolySegment callback
    
    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 531140e..5b90941 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -6299,6 +6299,13 @@ out:
 	RegionUninit(&data.region);
 }
 
+static void
+sna_poly_line__cpu(DrawablePtr drawable, GCPtr gc,
+		   int mode, int n, DDXPointPtr pt)
+{
+	fbPolyLine(drawable, gc, mode, n, pt);
+}
+
 static Bool
 sna_poly_segment_blt(DrawablePtr drawable,
 		     struct kgem_bo *bo,
@@ -10973,7 +10980,7 @@ static const GCOps sna_gc_ops__cpu = {
 	sna_copy_area,
 	sna_copy_plane,
 	sna_poly_point__cpu,
-	sna_poly_line,
+	sna_poly_line__cpu,
 	sna_poly_segment,
 	sna_poly_rectangle,
 	sna_poly_arc,
commit b8b49ae70b3aadf4423bd6830c446c040f87a2f1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 16:32:40 2012 +0000

    sna: Mutate a temporary copy of the GC->ops so we don't alter new GCs
    
    In order to avoid using the wrong function for a scratch GC created
    during the course of a MI function whilst we have a specialised GC in
    use, we need to avoid modifying the original function table.
    
    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 fea5167..531140e 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -125,6 +125,10 @@ static const uint8_t fill_ROP[] = {
 	ROP_1
 };
 
+static const GCOps sna_gc_ops;
+static const GCOps sna_gc_ops__cpu;
+static GCOps sna_gc_ops__tmp;
+
 static inline void region_set(RegionRec *r, const BoxRec *b)
 {
 	r->extents = *b;
@@ -6209,9 +6213,9 @@ spans_fallback:
 
 			if ((data.flags & 2) == 0) {
 				if (data.dx | data.dy)
-					gc->ops->FillSpans = sna_fill_spans__fill_offset;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill;
 			} else {
 				region_maybe_clip(&data.region,
 						  gc->pCompositeClip);
@@ -6219,12 +6223,13 @@ spans_fallback:
 					return;
 
 				if (region_is_singular(&data.region))
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_extents;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes;
 			}
 			assert(gc->miTranslate);
 
+			gc->ops = &sna_gc_ops__tmp;
 			miZeroLine(drawable, gc, mode, n, pt);
 			fill.done(data.sna, &fill);
 		} else {
@@ -6233,7 +6238,8 @@ spans_fallback:
 			 * FillSpans.
 			 */
 			data.bo = priv->gpu_bo;
-			gc->ops->FillSpans = sna_fill_spans__gpu;
+			sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu;
+			gc->ops = &sna_gc_ops__tmp;
 
 			switch (gc->lineStyle) {
 			default:
@@ -6260,7 +6266,7 @@ spans_fallback:
 			}
 		}
 
-		gc->ops->FillSpans = sna_fill_spans;
+		gc->ops = (GCOps *)&sna_gc_ops;
 		if (data.damage)
 			sna_damage_add(data.damage, &data.region);
 		RegionUninit(&data.region);
@@ -6282,12 +6288,13 @@ fallback:
 
 	/* Install FillSpans in case we hit a fallback path in fbPolyLine */
 	sna_gc(gc)->priv = &data.region;
-	gc->ops->FillSpans = sna_fill_spans__cpu;
+	assert(gc->ops == (GCOps *)&sna_gc_ops);
+	gc->ops = (GCOps *)&sna_gc_ops__cpu;
 
 	DBG(("%s: fbPolyLine\n", __FUNCTION__));
 	fbPolyLine(drawable, gc, mode, n, pt);
 
-	gc->ops->FillSpans = sna_fill_spans;
+	gc->ops = (GCOps *)&sna_gc_ops;
 out:
 	RegionUninit(&data.region);
 }
@@ -7144,9 +7151,9 @@ spans_fallback:
 
 			if ((data.flags & 2) == 0) {
 				if (data.dx | data.dy)
-					gc->ops->FillSpans = sna_fill_spans__fill_offset;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill;
 			} else {
 				region_maybe_clip(&data.region,
 						  gc->pCompositeClip);
@@ -7154,11 +7161,12 @@ spans_fallback:
 					return;
 
 				if (region_is_singular(&data.region))
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_extents;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes;
 			}
 			assert(gc->miTranslate);
+			gc->ops = &sna_gc_ops__tmp;
 			for (i = 0; i < n; i++)
 				line(drawable, gc, CoordModeOrigin, 2,
 				     (DDXPointPtr)&seg[i]);
@@ -7166,14 +7174,15 @@ spans_fallback:
 			fill.done(data.sna, &fill);
 		} else {
 			data.bo = priv->gpu_bo;
-			gc->ops->FillSpans = sna_fill_spans__gpu;
+			sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu;
+			gc->ops = &sna_gc_ops__tmp;
 
 			for (i = 0; i < n; i++)
 				line(drawable, gc, CoordModeOrigin, 2,
 				     (DDXPointPtr)&seg[i]);
 		}
 
-		gc->ops->FillSpans = sna_fill_spans;
+		gc->ops = (GCOps *)&sna_gc_ops;
 		if (data.damage)
 			sna_damage_add(data.damage, &data.region);
 		RegionUninit(&data.region);
@@ -7195,12 +7204,13 @@ fallback:
 
 	/* Install FillSpans in case we hit a fallback path in fbPolySegment */
 	sna_gc(gc)->priv = &data.region;
-	gc->ops->FillSpans = sna_fill_spans__cpu;
+	assert(gc->ops == (GCOps *)&sna_gc_ops);
+	gc->ops = (GCOps *)&sna_gc_ops__cpu;
 
 	DBG(("%s: fbPolySegment\n", __FUNCTION__));
 	fbPolySegment(drawable, gc, n, seg);
 
-	gc->ops->FillSpans = sna_fill_spans;
+	gc->ops = (GCOps *)&sna_gc_ops;
 out:
 	RegionUninit(&data.region);
 }
@@ -7871,10 +7881,10 @@ sna_poly_arc(DrawablePtr drawable, GCPtr gc, int n, xArc *arc)
 
 			if ((data.flags & 2) == 0) {
 				if (data.dx | data.dy)
-					gc->ops->FillSpans = sna_fill_spans__fill_offset;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill;
-				gc->ops->PolyPoint = sna_poly_point__fill;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill;
+				sna_gc_ops__tmp.PolyPoint = sna_poly_point__fill;
 			} else {
 				region_maybe_clip(&data.region,
 						  gc->pCompositeClip);
@@ -7882,21 +7892,20 @@ sna_poly_arc(DrawablePtr drawable, GCPtr gc, int n, xArc *arc)
 					return;
 
 				if (region_is_singular(&data.region)) {
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_extents;
-					gc->ops->PolyPoint = sna_poly_point__fill_clip_extents;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents;
+					sna_gc_ops__tmp.PolyPoint = sna_poly_point__fill_clip_extents;
 				} else {
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes;
-					gc->ops->PolyPoint = sna_poly_point__fill_clip_boxes;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes;
+					sna_gc_ops__tmp.PolyPoint = sna_poly_point__fill_clip_boxes;
 				}
 			}
 			assert(gc->miTranslate);
+			gc->ops = &sna_gc_ops__tmp;
 			if (gc->lineWidth == 0)
 				miZeroPolyArc(drawable, gc, n, arc);
 			else
 				miPolyArc(drawable, gc, n, arc);
-
-			gc->ops->PolyPoint = sna_poly_point;
-			gc->ops->FillSpans = sna_fill_spans;
+			gc->ops = (GCOps *)&sna_gc_ops;
 
 			fill.done(data.sna, &fill);
 			if (data.damage)
@@ -7928,14 +7937,13 @@ fallback:
 
 	/* Install FillSpans in case we hit a fallback path in fbPolyArc */
 	sna_gc(gc)->priv = &data.region;
-	gc->ops->FillSpans = sna_fill_spans__cpu;
-	gc->ops->PolyPoint = sna_poly_point__cpu;
+	assert(gc->ops == (GCOps *)&sna_gc_ops);
+	gc->ops = (GCOps *)&sna_gc_ops__cpu;
 
 	DBG(("%s -- fbPolyArc\n", __FUNCTION__));
 	fbPolyArc(drawable, gc, n, arc);
 
-	gc->ops->PolyPoint = sna_poly_point;
-	gc->ops->FillSpans = sna_fill_spans;
+	gc->ops = (GCOps *)&sna_gc_ops;
 out:
 	RegionUninit(&data.region);
 }
@@ -8218,9 +8226,9 @@ sna_poly_fill_polygon(DrawablePtr draw, GCPtr gc,
 
 			if ((data.flags & 2) == 0) {
 				if (data.dx | data.dy)
-					gc->ops->FillSpans = sna_fill_spans__fill_offset;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill;
 			} else {
 				region_maybe_clip(&data.region,
 						  gc->pCompositeClip);
@@ -8228,22 +8236,24 @@ sna_poly_fill_polygon(DrawablePtr draw, GCPtr gc,
 					return;
 
 				if (region_is_singular(&data.region))
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_extents;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes;
 			}
 			assert(gc->miTranslate);
+			gc->ops = &sna_gc_ops__tmp;
 
 			miFillPolygon(draw, gc, shape, mode, n, pt);
 			fill.done(data.sna, &fill);
 		} else {
 			data.bo = priv->gpu_bo;
-			gc->ops->FillSpans = sna_fill_spans__gpu;
+			sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu;
+			gc->ops = &sna_gc_ops__tmp;
 
 			miFillPolygon(draw, gc, shape, mode, n, pt);
 		}
 
-		gc->ops->FillSpans = sna_fill_spans;
+		gc->ops = (GCOps *)&sna_gc_ops;
 		if (data.damage)
 			sna_damage_add(data.damage, &data.region);
 		RegionUninit(&data.region);
@@ -8270,10 +8280,11 @@ fallback:
 	DBG(("%s: fallback -- miFillPolygon -> sna_fill_spans__cpu\n",
 	     __FUNCTION__));
 	sna_gc(gc)->priv = &data.region;
-	gc->ops->FillSpans = sna_fill_spans__cpu;
+	assert(gc->ops == (GCOps *)&sna_gc_ops);
+	gc->ops = (GCOps *)&sna_gc_ops__cpu;
 
 	miFillPolygon(draw, gc, shape, mode, n, pt);
-	gc->ops->FillSpans = sna_fill_spans;
+	gc->ops = (GCOps *)&sna_gc_ops;
 out:
 	RegionUninit(&data.region);
 }
@@ -9745,9 +9756,9 @@ sna_poly_fill_arc(DrawablePtr draw, GCPtr gc, int n, xArc *arc)
 
 			if ((data.flags & 2) == 0) {
 				if (data.dx | data.dy)
-					gc->ops->FillSpans = sna_fill_spans__fill_offset;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_offset;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill;
 			} else {
 				region_maybe_clip(&data.region,
 						  gc->pCompositeClip);
@@ -9755,22 +9766,24 @@ sna_poly_fill_arc(DrawablePtr draw, GCPtr gc, int n, xArc *arc)
 					return;
 
 				if (region_is_singular(&data.region))
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_extents;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_extents;
 				else
-					gc->ops->FillSpans = sna_fill_spans__fill_clip_boxes;
+					sna_gc_ops__tmp.FillSpans = sna_fill_spans__fill_clip_boxes;
 			}
 			assert(gc->miTranslate);
+			gc->ops = &sna_gc_ops__tmp;
 
 			miPolyFillArc(draw, gc, n, arc);
 			fill.done(data.sna, &fill);
 		} else {
 			data.bo = priv->gpu_bo;
-			gc->ops->FillSpans = sna_fill_spans__gpu;
+			sna_gc_ops__tmp.FillSpans = sna_fill_spans__gpu;
+			gc->ops = &sna_gc_ops__tmp;
 
 			miPolyFillArc(draw, gc, n, arc);
 		}
 
-		gc->ops->FillSpans = sna_fill_spans;
+		gc->ops = (GCOps *)&sna_gc_ops;
 		if (data.damage)
 			sna_damage_add(data.damage, &data.region);
 		RegionUninit(&data.region);
@@ -9797,10 +9810,11 @@ fallback:
 	DBG(("%s: fallback -- miFillPolygon -> sna_fill_spans__cpu\n",
 	     __FUNCTION__));
 	sna_gc(gc)->priv = &data.region;
-	gc->ops->FillSpans = sna_fill_spans__cpu;
+	assert(gc->ops == (GCOps *)&sna_gc_ops);
+	gc->ops = (GCOps *)&sna_gc_ops__cpu;
 
 	miPolyFillArc(draw, gc, n, arc);
-	gc->ops->FillSpans = sna_fill_spans;
+	gc->ops = (GCOps *)&sna_gc_ops;
 out:
 	RegionUninit(&data.region);
 }
@@ -10929,7 +10943,53 @@ out:
 	RegionUninit(&region);
 }
 
-static GCOps sna_gc_ops = {
+static const GCOps sna_gc_ops = {
+	sna_fill_spans,
+	sna_set_spans,
+	sna_put_image,
+	sna_copy_area,
+	sna_copy_plane,
+	sna_poly_point,
+	sna_poly_line,
+	sna_poly_segment,
+	sna_poly_rectangle,
+	sna_poly_arc,
+	sna_poly_fill_polygon,
+	sna_poly_fill_rect,
+	sna_poly_fill_arc,
+	sna_poly_text8,
+	sna_poly_text16,
+	sna_image_text8,
+	sna_image_text16,
+	sna_image_glyph,
+	sna_poly_glyph,
+	sna_push_pixels,
+};
+
+static const GCOps sna_gc_ops__cpu = {
+	sna_fill_spans__cpu,
+	sna_set_spans,
+	sna_put_image,
+	sna_copy_area,
+	sna_copy_plane,
+	sna_poly_point__cpu,
+	sna_poly_line,
+	sna_poly_segment,
+	sna_poly_rectangle,
+	sna_poly_arc,
+	sna_poly_fill_polygon,
+	sna_poly_fill_rect,
+	sna_poly_fill_arc,
+	sna_poly_text8,
+	sna_poly_text16,
+	sna_image_text8,
+	sna_image_text16,
+	sna_image_glyph,
+	sna_poly_glyph,
+	sna_push_pixels,
+};
+
+static GCOps sna_gc_ops__tmp = {
 	sna_fill_spans,
 	sna_set_spans,
 	sna_put_image,
@@ -10965,7 +11025,7 @@ sna_validate_gc(GCPtr gc, unsigned long changes, DrawablePtr drawable)
 	sna_gc(gc)->changes |= changes;
 }
 
-static GCFuncs sna_gc_funcs = {
+static const GCFuncs sna_gc_funcs = {
 	sna_validate_gc,
 	miChangeGC,
 	miCopyGC,
@@ -10980,8 +11040,8 @@ static int sna_create_gc(GCPtr gc)
 	if (!fbCreateGC(gc))
 		return FALSE;
 
-	gc->funcs = &sna_gc_funcs;
-	gc->ops = &sna_gc_ops;
+	gc->funcs = (GCFuncs *)&sna_gc_funcs;
+	gc->ops = (GCOps *)&sna_gc_ops;
 	return TRUE;
 }
 
commit 1a116a15a5d978a1edf413a439f6ef6d3205a7aa
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 16:53:21 2012 +0000

    sna: Reduce the assertion that we would have hinted to operate inplace
    
    As the drawable_gc_flags() operate on lower level information than the
    hint, it is able to spot more oportunities to reduce the READ flags and
    so the assertion was overly optimistic.
    
    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 0cf7fac..fea5167 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -1482,8 +1482,8 @@ inline static unsigned drawable_gc_flags(DrawablePtr draw,
 		return MOVE_READ | MOVE_WRITE;
 	}
 
-	DBG(("%s: try operating on drawable inplace\n", __FUNCTION__));
-	assert(drawable_gc_inplace_hint(draw, gc));
+	DBG(("%s: try operating on drawable inplace [hint? %d]\n",
+	     __FUNCTION__, drawable_gc_inplace_hint(draw, gc)));
 
 	flags = MOVE_WRITE;
 	if (USE_INPLACE)
commit 3d1bba033bc29fdf498dc082f3542c520a5ed39a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 18:22:12 2012 +0000

    sna/gen3: Apply damage to video pixmap
    
    Reported-by: Paul Neumann <paul104x at yahoo.de>
    References: https://bugs.freedesktop.org/show_bug.cgi?id=44504
    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 4b61f65..acccf0a 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -3610,6 +3610,7 @@ gen3_render_video(struct sna *sna,
 		  short drw_w, short drw_h,
 		  PixmapPtr pixmap)
 {
+	struct sna_pixmap *priv = sna_pixmap(pixmap);
 	BoxPtr pbox = REGION_RECTS(dstRegion);
 	int nbox = REGION_NUM_RECTS(dstRegion);
 	int dxo = dstRegion->extents.x1;
@@ -3623,7 +3624,7 @@ gen3_render_video(struct sna *sna,
 
 	DBG(("%s: %dx%d -> %dx%d\n", __FUNCTION__, src_w, src_h, drw_w, drw_h));
 
-	dst_bo = sna_pixmap_get_bo(pixmap);
+	dst_bo = priv->gpu_bo;
 	if (dst_bo == NULL)
 		return FALSE;
 
@@ -3721,7 +3722,7 @@ gen3_render_video(struct sna *sna,
 #endif
 		sna_blt_copy_boxes(sna, GXcopy,
 				   dst_bo, -dxo, -dyo,
-				   sna_pixmap_get_bo(pixmap), pix_xoff, pix_yoff,
+				   priv->gpu_bo, pix_xoff, pix_yoff,
 				   pixmap->drawable.bitsPerPixel,
 				   REGION_RECTS(dstRegion),
 				   REGION_NUM_RECTS(dstRegion));
@@ -3729,6 +3730,22 @@ gen3_render_video(struct sna *sna,
 		kgem_bo_destroy(&sna->kgem, dst_bo);
 	}
 
+	if (!DAMAGE_IS_ALL(priv->gpu_damage)) {
+		if ((pix_xoff | pix_yoff) == 0) {
+			sna_damage_add(&priv->gpu_damage, dstRegion);
+			sna_damage_subtract(&priv->cpu_damage, dstRegion);
+		} else {
+			sna_damage_add_boxes(&priv->gpu_damage,
+					     REGION_RECTS(dstRegion),
+					     REGION_NUM_RECTS(dstRegion),
+					     pix_xoff, pix_yoff);
+			sna_damage_subtract_boxes(&priv->cpu_damage,
+						  REGION_RECTS(dstRegion),
+						  REGION_NUM_RECTS(dstRegion),
+						  pix_xoff, pix_yoff);
+		}
+	}
+
 	return TRUE;
 }
 
diff --git a/src/sna/sna_damage.c b/src/sna/sna_damage.c
index 490e7a9..d15ec60 100644
--- a/src/sna/sna_damage.c
+++ b/src/sna/sna_damage.c
@@ -1148,6 +1148,88 @@ fastcall struct sna_damage *_sna_damage_subtract_box(struct sna_damage *damage,
 }
 #endif
 
+static struct sna_damage *__sna_damage_subtract_boxes(struct sna_damage *damage,
+						      const BoxRec *box, int n,
+						      int dx, int dy)
+{
+	BoxRec extents;
+	int i;
+
+	if (damage == NULL)
+		return NULL;
+
+	assert(n);
+
+	extents = box[0];
+	for (i = 1; i < n; i++) {
+		if (extents.x1 > box[i].x1)
+			extents.x1 = box[i].x1;
+		if (extents.x2 < box[i].x2)
+			extents.x2 = box[i].x2;
+		if (extents.y1 > box[i].y1)
+			extents.y1 = box[i].y1;
+		if (extents.y2 < box[i].y2)
+			extents.y2 = box[i].y2;
+	}
+
+	assert(extents.y2 > extents.y1 && extents.x2 > extents.x1);
+
+	extents.x1 += dx;
+	extents.x2 += dx;
+	extents.y1 += dy;
+	extents.y2 += dy;
+
+	if (!sna_damage_maybe_contains_box(damage, &extents))
+		return damage;
+
+	if (n == 1)
+		return __sna_damage_subtract_box(damage, &extents);
+
+	if (damage->mode != DAMAGE_SUBTRACT) {
+		if (damage->dirty)
+			__sna_damage_reduce(damage);
+
+		if (!pixman_region_not_empty(&damage->region)) {
+			__sna_damage_destroy(damage);
+			return NULL;
+		}
+
+		damage->mode = DAMAGE_SUBTRACT;
+	}
+
+	return _sna_damage_create_elt_from_boxes(damage, box, n, dx, dy);
+}
+
+#if DEBUG_DAMAGE
+fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
+						       const BoxRec *box, int n,
+						       int dx, int dy)
+{
+	char damage_buf[1000];
+	char region_buf[120];
+
+	ErrorF("%s(%s - [(%d,%d), (%d,%d)...x%d])...\n", __FUNCTION__,
+	       _debug_describe_damage(damage_buf, sizeof(damage_buf), damage),
+	       box->x1 + dx, box->y1 + dy,
+	       box->x2 + dx, box->y2 + dy,
+	       n);
+
+	damage = __sna_damage_subtract_boxes(damage, box, n, dx, dy);
+
+	ErrorF("  = %s\n",
+	       _debug_describe_damage(damage_buf, sizeof(damage_buf), damage));
+
+	return damage;
+}
+#else
+fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
+						       const BoxRec *box, int n,
+						       int dx, int dy)
+{
+	return __sna_damage_subtract_boxes(damage, box, n, dx, dy);
+}
+#endif
+
 static int __sna_damage_contains_box(struct sna_damage *damage,
 				     const BoxRec *box)
 {
diff --git a/src/sna/sna_damage.h b/src/sna/sna_damage.h
index dc0962f..228aba0 100644
--- a/src/sna/sna_damage.h
+++ b/src/sna/sna_damage.h
@@ -153,6 +153,18 @@ static inline void sna_damage_subtract_box(struct sna_damage **damage,
 	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
 }
 
+fastcall struct sna_damage *_sna_damage_subtract_boxes(struct sna_damage *damage,
+						       const BoxRec *box, int n,
+						       int dx, int dy);
+static inline void sna_damage_subtract_boxes(struct sna_damage **damage,
+					     const BoxRec *box, int n,
+					     int dx, int dy)
+{
+	*damage = _sna_damage_subtract_boxes(DAMAGE_PTR(*damage),
+					     box, n, dx, dy);
+	assert(*damage == NULL || (*damage)->mode != DAMAGE_ALL);
+}
+
 Bool _sna_damage_intersect(struct sna_damage *damage,
 			  RegionPtr region, RegionPtr result);
 
commit ff4b8a03a40f7eb1d71b96aebb5daa1d8df83d2a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 17:51:35 2012 +0000

    sna: Use RepeatPad to avoid sampling the border color when downsampling
    
    References: https://bugs.freedesktop.org/show_bug.cgi?id=45086
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/kgem.c b/src/sna/kgem.c
index d8a3017..b979d3c 100644
--- a/src/sna/kgem.c
+++ b/src/sna/kgem.c
@@ -3278,6 +3278,7 @@ struct kgem_bo *kgem_upload_source_image_halved(struct kgem *kgem,
 	t.matrix[2][2] = 1 << 16;
 	pixman_image_set_transform(src_image, &t);
 	pixman_image_set_filter(src_image, PIXMAN_FILTER_BILINEAR, NULL, 0);
+	pixman_image_set_repeat(src_image, PIXMAN_REPEAT_PAD);
 
 	pixman_image_composite(PIXMAN_OP_SRC,
 			       src_image, NULL, dst_image,
diff --git a/src/sna/sna_render.c b/src/sna/sna_render.c
index 4f86137..56d0014 100644
--- a/src/sna/sna_render.c
+++ b/src/sna/sna_render.c
@@ -737,6 +737,8 @@ static int sna_render_picture_downsample(struct sna *sna,
 
 		tmp_src = CreatePicture(0, &pixmap->drawable, format, 0, NULL,
 					serverClient, &error);
+		tmp_src->repeat = true;
+		tmp_src->repeatType = RepeatPad;
 		tmp_src->filter = PictFilterBilinear;
 		memset(&t, 0, sizeof(t));
 		t.matrix[0][0] = 2 << 16;
commit 09bddddaf94b848f417e1c9449cfe4b21d2554dd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 15:50:02 2012 +0000

    sna: handle negative modulus for tiled blits
    
    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 70b712a..0cf7fac 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -8330,17 +8330,22 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
 		do {
 			xRectangle r = *rect++;
 			int16_t tile_y = (r.y - origin->y) % tile_height;
+			if (tile_y < 0)
+				tile_y += tile_height;
 
 			r.y += dy;
 			do {
 				int16_t width = r.width;
-				int16_t x = r.x + dx;
-				int16_t tile_x = (r.x - origin->x) % tile_width;
+				int16_t x = r.x + dx, tile_x;
 				int16_t h = tile_height - tile_y;
 				if (h > r.height)
 					h = r.height;
 				r.height -= h;
 
+				tile_x = (r.x - origin->x) % tile_width;
+				if (tile_x < 0)
+					tile_x += tile_width;
+
 				do {
 					int16_t w = tile_width - tile_x;
 					if (w > width)
@@ -8382,15 +8387,21 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
 					int height = r.y2 - r.y1;
 					int dst_y = r.y1;
 					int tile_y = (r.y1 - drawable->y - origin->y) % tile_height;
+					if (tile_y < 0)
+						tile_y += tile_height;
+
 					while (height) {
 						int width = r.x2 - r.x1;
-						int dst_x = r.x1;
-						int tile_x = (r.x1 - drawable->x - origin->x) % tile_width;
+						int dst_x = r.x1, tile_x;
 						int h = tile_height - tile_y;
 						if (h > height)
 							h = height;
 						height -= h;
 
+						tile_x = (r.x1 - drawable->x - origin->x) % tile_width;
+						if (tile_x < 0)
+							tile_x += tile_width;
+
 						while (width > 0) {
 							int w = tile_width - tile_x;
 							if (w > width)
@@ -8442,15 +8453,21 @@ sna_poly_fill_rect_tiled_blt(DrawablePtr drawable,
 					int height = box->y2 - box->y1;
 					int dst_y = box->y1;
 					int tile_y = (box->y1 - drawable->y - origin->y) % tile_height;
+					if (tile_y < 0)
+						tile_y += tile_height;
+
 					while (height) {
 						int width = box->x2 - box->x1;
-						int dst_x = box->x1;
-						int tile_x = (box->x1 - drawable->x - origin->x) % tile_width;
+						int dst_x = box->x1, tile_x;
 						int h = tile_height - tile_y;
 						if (h > height)
 							h = height;
 						height -= h;
 
+						tile_x = (box->x1 - drawable->x - origin->x) % tile_width;
+						if (tile_x < 0)
+							tile_x += tile_width;
+
 						while (width > 0) {
 							int w = tile_width - tile_x;
 							if (w > width)
commit f3b11ebc28114062581c39089781114323946654
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 16:05:09 2012 +0000

    sna: Add more assertions for copy errors
    
    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 a6e211d..70b712a 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -3495,6 +3495,17 @@ fallback:
 				     src_dx, src_dy,
 				     dst_dx, dst_dy,
 				     src_stride, dst_stride));
+
+				assert(box->x1 + src_dx >= 0);
+				assert(box->y1 + src_dy >= 0);
+				assert(box->x2 + src_dx <= src_pixmap->drawable.width);
+				assert(box->y2 + src_dy <= src_pixmap->drawable.height);
+
+				assert(box->x1 + dst_dx >= 0);
+				assert(box->y1 + dst_dy >= 0);
+				assert(box->x2 + dst_dx <= dst_pixmap->drawable.width);
+				assert(box->y2 + dst_dy <= dst_pixmap->drawable.height);
+
 				memcpy_blt(src_bits, dst_bits, bpp,
 					   src_stride, dst_stride,
 					   box->x1, box->y1,
commit b56971986d2d495aa38f015beb659fb12f0d433a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jan 24 17:23:59 2012 +0000

    sna: Trim the clipped Segment to the right length
    
    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 4b997a5..a6e211d 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -6687,12 +6687,6 @@ rectangle_continue:
 						continue;
 
 					length = abs(x2 - x1);
-
-					/* if we've clipped the endpoint, always draw the full length
-					 * of the segment, because then the capstyle doesn't matter
-					 */
-					if (pt2_clipped)
-						length++;
 					if (length == 0)
 						continue;
 
@@ -6713,7 +6707,7 @@ rectangle_continue:
 
 				b->x1 = x1;
 				b->y2 = b->y1 = y1;
-				while (length--) {
+				while (--length) {
 					e += e1;
 					x1++;
 					if (e >= 0) {
@@ -6765,12 +6759,6 @@ X_continue2:
 						continue;
 
 					length = abs(y2 - y1);
-
-					/* if we've clipped the endpoint, always draw the full length
-					 * of the segment, because then the capstyle doesn't matter
-					 */
-					if (pt2_clipped)
-						length++;
 					if (length == 0)
 						continue;
 
@@ -6792,7 +6780,7 @@ X_continue2:
 
 				b->x2 = b->x1 = x1;
 				b->y1 = y1;
-				while (length--) {
+				while (--length) {
 					e += e1;
 					y1 += sdy;
 					if (e >= 0) {


More information about the xorg-commit mailing list