xf86-video-intel: 4 commits - src/sna/sna_accel.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Oct 27 08:30:24 PDT 2011


 src/sna/sna_accel.c |  663 ++++++++++++++++++++++++++++++++--------------------
 1 file changed, 409 insertions(+), 254 deletions(-)

New commits:
commit c7bd89fb54686c14b687c007e42c34c23423b0fd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 27 16:23:35 2011 +0100

    sna: Fix PolyPoint not to always send 512 boxes
    
    Just emit the remaining boxes!
    
    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 76e412f..58ef208 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2377,7 +2377,7 @@ sna_poly_point_blt(DrawablePtr drawable,
 			}
 		} while (--n);
 		if (b != box)
-			fill.boxes(sna, &fill, box, last_box - box);
+			fill.boxes(sna, &fill, box, b - box);
 	} else {
 		while (n--) {
 			int x, y;
@@ -4372,7 +4372,7 @@ wide:
 			if (b+4 > last_box) {
 				fill.boxes(sna, &fill, boxes, last_box-boxes);
 				if (damage)
-					sna_damage_add_boxes(damage, boxes, b-boxes, 0, 0);
+					sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
 				b = boxes;
 			}
 
@@ -4711,7 +4711,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
 					if (++b == last_box) {
 						fill.boxes(sna, &fill, boxes, last_box-boxes);
 						if (damage)
-							sna_damage_add_boxes(damage, boxes, b-boxes, 0, 0);
+							sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
 						b = boxes;
 					}
 				}
commit cfd5b7f6ce80af911bfc8b71bba776ea814e307a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 27 15:28:11 2011 +0100

    sna: Use fill->boxes to pack PolyFillRectangle
    
    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 3df889a..76e412f 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -4624,12 +4624,13 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
 		       struct sna_damage **damage,
 		       GCPtr gc, int n,
 		       xRectangle *rect,
+		       const BoxRec *extents,
 		       bool clipped)
 {
 	struct sna *sna = to_sna_from_drawable(drawable);
 	PixmapPtr pixmap = get_drawable_pixmap(drawable);
-	RegionPtr clip = fbGetCompositeClip(gc);
 	struct sna_fill_op fill;
+	BoxRec boxes[512], *b = boxes, *const last_box = boxes+ARRAY_SIZE(boxes);
 	uint32_t pixel = gc->fillStyle == FillSolid ? gc->fgPixel : gc->tile.pixel;
 	int16_t dx, dy;
 
@@ -4638,8 +4639,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
 	     n, rect->x, rect->y, rect->width, rect->height,
 	     clipped));
 
-	if (n == 1 && clip->data == NULL) {
-		BoxPtr box = &clip->extents;
+	if (n == 1 && gc->pCompositeClip->data == NULL) {
 		BoxRec r;
 		bool success = true;
 
@@ -4647,7 +4647,7 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
 		r.y1 = rect->y + drawable->y;
 		r.x2 = bound(r.x1, rect->width);
 		r.y2 = bound(r.y1, rect->height);
-		if (box_intersect(&r, box)) {
+		if (box_intersect(&r, &gc->pCompositeClip->extents)) {
 			get_drawable_deltas(drawable, pixmap, &dx, &dy);
 			r.x1 += dx; r.y1 += dy;
 			r.x2 += dx; r.y2 += dy;
@@ -4677,72 +4677,89 @@ sna_poly_fill_rect_blt(DrawablePtr drawable,
 
 		sna_damage_add_rectangles(damage, rect, n, dx, dy);
 		do {
-			BoxRec r;
-
-			r.x1 = rect->x + dx;
-			r.y1 = rect->y + dy;
-			r.x2 = bound(r.x1, rect->width);
-			r.y2 = bound(r.y1, rect->height);
+			b->x1 = rect->x + dx;
+			b->y1 = rect->y + dy;
+			b->x2 = b->x1 + rect->width;
+			b->y2 = b->y1 + rect->height;
 			rect++;
-
-			fill.box(sna, &fill, &r);
+			if (++b == last_box) {
+				fill.boxes(sna, &fill, boxes, last_box-boxes);
+				b = boxes;
+			}
 		} while (--n);
-	} else if (clip->data == NULL) {
-		BoxPtr box = &clip->extents;
-		while (n--) {
-			BoxRec r;
+	} else {
+		RegionRec clip;
 
-			r.x1 = rect->x + drawable->x;
-			r.y1 = rect->y + drawable->y;
-			r.x2 = bound(r.x1, rect->width);
-			r.y2 = bound(r.y1, rect->height);
-			rect++;
+		region_set(&clip, extents);
+		region_maybe_clip(&clip, gc->pCompositeClip);
+		if (!RegionNotEmpty(&clip))
+			goto done;
 
-			if (box_intersect(&r, box)) {
-				r.x1 += dx;
-				r.x2 += dx;
-				r.y1 += dy;
-				r.y2 += dy;
-				fill.box(sna, &fill, &r);
-				if (damage) {
-					assert_pixmap_contains_box(pixmap, &r);
-					sna_damage_add_box(damage, &r);
-				}
-			}
-		}
-	} else {
-		while (n--) {
-			RegionRec region;
-			BoxRec *box;
-			int nbox;
-
-			region.extents.x1 = rect->x + drawable->x;
-			region.extents.y1 = rect->y + drawable->y;
-			region.extents.x2 = bound(region.extents.x1, rect->width);
-			region.extents.y2 = bound(region.extents.y1, rect->height);
-			rect++;
+		if (clip.data == NULL) {
+			do {
+				b->x1 = rect->x + drawable->x;
+				b->y1 = rect->y + drawable->y;
+				b->x2 = bound(b->x1, rect->width);
+				b->y2 = bound(b->y1, rect->height);
+				rect++;
 
-			region.data = NULL;
-			RegionIntersect(&region, &region, clip);
-
-			nbox = REGION_NUM_RECTS(&region);
-			box = REGION_RECTS(&region);
-			while (nbox--) {
-				box->x1 += dx;
-				box->x2 += dx;
-				box->y1 += dy;
-				box->y2 += dy;
-				fill.box(sna, &fill, box);
-				if (damage) {
-					assert_pixmap_contains_box(pixmap, box);
-					sna_damage_add_box(damage, box);
+				if (box_intersect(b, &clip.extents)) {
+					b->x1 += dx;
+					b->x2 += dx;
+					b->y1 += dy;
+					b->y2 += dy;
+					if (++b == last_box) {
+						fill.boxes(sna, &fill, boxes, last_box-boxes);
+						if (damage)
+							sna_damage_add_boxes(damage, boxes, b-boxes, 0, 0);
+						b = boxes;
+					}
 				}
-				box++;
-			}
+			} while (--n);
+		} else {
+			const BoxRec * const clip_start = RegionBoxptr(&clip);
+			const BoxRec * const clip_end = clip_start + clip.data->numRects;
+			const BoxRec *c;
+
+			do {
+				BoxRec box;
+
+				box.x1 = rect->x + drawable->x;
+				box.y1 = rect->y + drawable->y;
+				box.x2 = bound(box.x1, rect->width);
+				box.y2 = bound(box.y1, rect->height);
+				rect++;
 
-			RegionUninit(&region);
+				c = find_clip_box_for_y(clip_start,
+							clip_end,
+							box.y1);
+				while (c != clip_end) {
+					if (box.y2 <= c->y1)
+						break;
+
+					*b = box;
+					if (box_intersect(b, c)) {
+						b->x1 += dx;
+						b->x2 += dx;
+						b->y1 += dy;
+						b->y2 += dy;
+						if (++b == last_box) {
+							fill.boxes(sna, &fill, boxes, last_box-boxes);
+							if (damage)
+								sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
+							b = boxes;
+						}
+					}
+
+				}
+			} while (--n);
 		}
+
+		RegionUninit(&clip);
 	}
+	if (b != boxes)
+		fill.boxes(sna, &fill, boxes, b-boxes);
+done:
 	fill.done(sna, &fill);
 	return TRUE;
 }
@@ -5000,11 +5017,8 @@ sna_poly_fill_rect_extents(DrawablePtr drawable, GCPtr gc,
 	box.x2 = bound(box.x1, rect->width);
 	box.y1 = rect->y;
 	box.y2 = bound(box.y1, rect->height);
-
-	while (--n) {
-		rect++;
-		box_add_rect(&box, rect);
-	}
+	while (--n)
+		box_add_rect(&box, ++rect);
 
 	clipped = trim_and_translate_box(&box, drawable, gc);
 	if (box_empty(&box))
@@ -5062,14 +5076,16 @@ sna_poly_fill_rect(DrawablePtr draw, GCPtr gc, int n, xRectangle *rect)
 		    sna_poly_fill_rect_blt(draw,
 					   priv->gpu_bo,
 					   priv->gpu_only ? NULL : reduce_damage(draw, &priv->gpu_damage, &region.extents),
-					   gc, n, rect, flags & 2))
+					   gc, n, rect,
+					   &region.extents, flags & 2))
 			return;
 
 		if (sna_drawable_use_cpu_bo(draw, &region.extents) &&
 		    sna_poly_fill_rect_blt(draw,
 					   priv->cpu_bo,
 					   reduce_damage(draw, &priv->cpu_damage, &region.extents),
-					   gc, n, rect, flags & 2))
+					   gc, n, rect,
+					   &region.extents, flags & 2))
 			return;
 	} else if (gc->fillStyle == FillTiled) {
 		struct sna_pixmap *priv = sna_pixmap_from_drawable(draw);
commit 8d304f47e35be344550f389158eac3d4c21d9440
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 27 14:43:46 2011 +0100

    sna: Use fill->boxes for rectilinear 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 d776103..3df889a 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2870,15 +2870,14 @@ sna_poly_line_blt(DrawablePtr drawable,
 		  struct kgem_bo *bo,
 		  struct sna_damage **damage,
 		  GCPtr gc, int mode, int n, DDXPointPtr pt,
-		  bool clipped)
+		  const BoxRec *extents, bool clipped)
 {
 	struct sna *sna = to_sna_from_drawable(drawable);
 	PixmapPtr pixmap = get_drawable_pixmap(drawable);
-	RegionPtr clip = fbGetCompositeClip(gc);
+	BoxRec boxes[512], *b = boxes, * const last_box = boxes + ARRAY_SIZE(boxes);
 	struct sna_fill_op fill;
 	DDXPointRec last;
 	int16_t dx, dy;
-	int first;
 
 	DBG(("%s: alu=%d, fg=%08lx\n", __FUNCTION__, gc->alu, gc->fgPixel));
 
@@ -2896,7 +2895,6 @@ sna_poly_line_blt(DrawablePtr drawable,
 		pt++;
 
 		while (--n) {
-			BoxRec r;
 			DDXPointRec p;
 
 			p = *pt++;
@@ -2908,104 +2906,169 @@ sna_poly_line_blt(DrawablePtr drawable,
 				p.y += dy;
 			}
 			if (last.x == p.x) {
-				r.x1 = last.x;
-				r.x2 = last.x + 1;
+				b->x1 = last.x;
+				b->x2 = last.x + 1;
 			} else if (last.x < p.x) {
-				r.x1 = last.x;
-				r.x2 = p.x;
+				b->x1 = last.x;
+				b->x2 = p.x;
 			} else {
-				r.x1 = p.x;
-				r.x2 = last.x;
+				b->x1 = p.x;
+				b->x2 = last.x;
 			}
 			if (last.y == p.y) {
-				r.y1 = last.y;
-				r.y2 = last.y + 1;
+				b->y1 = last.y;
+				b->y2 = last.y + 1;
 			} else if (last.y < p.y) {
-				r.y1 = last.y;
-				r.y2 = p.y;
+				b->y1 = last.y;
+				b->y2 = p.y;
 			} else {
-				r.y1 = p.y;
-				r.y2 = last.y;
+				b->y1 = p.y;
+				b->y2 = last.y;
 			}
 			DBG(("%s: blt (%d, %d), (%d, %d)\n",
 			     __FUNCTION__,
-			     r.x1, r.y1, r.x2, r.y2));
-			fill.box(sna, &fill, &r);
-			if (damage) {
-				assert_pixmap_contains_box(pixmap, &r);
-				sna_damage_add_box(damage, &r);
+			     b->x1, b->y1, b->x2, b->y2));
+			if (++b == last_box) {
+				fill.boxes(sna, &fill, boxes, last_box - boxes);
+				if (damage)
+					sna_damage_add_boxes(damage, boxes, last_box - boxes, 0, 0);
+				b = boxes;
 			}
 
 			last = p;
 		}
 	} else {
-		last.x = drawable->x;
-		last.y = drawable->y;
-		first = 1;
+		RegionRec clip;
 
-		while (n--) {
-			int nclip;
-			BoxPtr box;
-			DDXPointRec p;
+		region_set(&clip, extents);
+		region_maybe_clip(&clip, gc->pCompositeClip);
 
-			p = *pt++;
-			if (mode == CoordModePrevious) {
-				p.x += last.x;
-				p.y += last.y;
-			} else {
-				p.x += drawable->x;
-				p.y += drawable->y;
-			}
+		last.x = pt->x + drawable->x;
+		last.y = pt->y + drawable->y;
+		pt++;
 
-			if (!first) {
-				for (nclip = REGION_NUM_RECTS(clip), box = REGION_RECTS(clip); nclip--; box++) {
-					BoxRec r;
+		if (clip.data == NULL) {
+			while (--n) {
+				DDXPointRec p;
 
-					if (last.x == p.x) {
-						r.x1 = last.x;
-						r.x2 = last.x + 1;
-					} else if (last.x < p.x) {
-						r.x1 = last.x;
-						r.x2 = p.x;
-					} else {
-						r.x1 = p.x;
-						r.x2 = last.x;
-					}
-					if (last.y == p.y) {
-						r.y1 = last.y;
-						r.y2 = last.y + 1;
-					} else if (last.y < p.y) {
-						r.y1 = last.y;
-						r.y2 = p.y;
-					} else {
-						r.y1 = p.y;
-						r.y2 = last.y;
+				p = *pt++;
+				if (mode == CoordModePrevious) {
+					p.x += last.x;
+					p.y += last.y;
+				} else {
+					p.x += drawable->x;
+					p.y += drawable->y;
+				}
+				if (last.x == p.x) {
+					b->x1 = last.x;
+					b->x2 = last.x + 1;
+				} else if (last.x < p.x) {
+					b->x1 = last.x;
+					b->x2 = p.x;
+				} else {
+					b->x1 = p.x;
+					b->x2 = last.x;
+				}
+				if (last.y == p.y) {
+					b->y1 = last.y;
+					b->y2 = last.y + 1;
+				} else if (last.y < p.y) {
+					b->y1 = last.y;
+					b->y2 = p.y;
+				} else {
+					b->y1 = p.y;
+					b->y2 = last.y;
+				}
+				DBG(("%s: blt (%d, %d), (%d, %d)\n",
+				     __FUNCTION__,
+				     b->x1, b->y1, b->x2, b->y2));
+				if (box_intersect(b, &clip.extents)) {
+					b->x1 += dx;
+					b->x2 += dx;
+					b->y1 += dy;
+					b->y2 += dy;
+					if (++b == last_box) {
+						fill.boxes(sna, &fill, boxes, last_box - boxes);
+						if (damage)
+							sna_damage_add_boxes(damage, boxes, last_box - boxes, 0, 0);
+						b = boxes;
 					}
-					DBG(("%s: (%d, %d) -> (%d, %d) clipping line (%d, %d), (%d, %d) against box (%d, %d), (%d, %d)\n",
-					     __FUNCTION__,
-					     last.x, last.y, p.x, p.y,
-					     r.x1, r.y1, r.x2, r.y2,
-					     box->x1, box->y1, box->x2, box->y2));
-					if (box_intersect(&r, box)) {
-						r.x1 += dx;
-						r.x2 += dx;
-						r.y1 += dy;
-						r.y2 += dy;
-						DBG(("%s: blt (%d, %d), (%d, %d)\n",
-						     __FUNCTION__,
-						     r.x1, r.y1, r.x2, r.y2));
-						fill.box(sna, &fill, &r);
-						if (damage) {
-							assert_pixmap_contains_box(pixmap, &r);
-							sna_damage_add_box(damage, &r);
+				}
+
+				last = p;
+			}
+		} else {
+			const BoxRec * const clip_start = RegionBoxptr(&clip);
+			const BoxRec * const clip_end = clip_start + clip.data->numRects;
+			const BoxRec *c;
+
+			while (--n) {
+				DDXPointRec p;
+				BoxRec box;
+
+				p = *pt++;
+				if (mode == CoordModePrevious) {
+					p.x += last.x;
+					p.y += last.y;
+				} else {
+					p.x += drawable->x;
+					p.y += drawable->y;
+				}
+				if (last.x == p.x) {
+					box.x1 = last.x;
+					box.x2 = last.x + 1;
+				} else if (last.x < p.x) {
+					box.x1 = last.x;
+					box.x2 = p.x;
+				} else {
+					box.x1 = p.x;
+					box.x2 = last.x;
+				}
+				if (last.y == p.y) {
+					box.y1 = last.y;
+					box.y2 = last.y + 1;
+				} else if (last.y < p.y) {
+					box.y1 = last.y;
+					box.y2 = p.y;
+				} else {
+					box.y1 = p.y;
+					box.y2 = last.y;
+				}
+				DBG(("%s: blt (%d, %d), (%d, %d)\n",
+				     __FUNCTION__,
+				     box.x1, box.y1, box.x2, box.y2));
+
+				c = find_clip_box_for_y(clip_start,
+							clip_end,
+							box.y1);
+				while (c != clip_end) {
+					if (box.y2 <= c->y1)
+						break;
+
+					*b = box;
+					if (box_intersect(b, c)) {
+						b->x1 += dx;
+						b->x2 += dx;
+						b->y1 += dy;
+						b->y2 += dy;
+						if (++b == last_box) {
+							fill.boxes(sna, &fill, boxes, last_box-boxes);
+							if (damage)
+								sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
+							b = boxes;
 						}
 					}
 				}
-			}
 
-			last = p;
-			first = 0;
+				last = p;
+			}
 		}
+		RegionUninit(&clip);
+	}
+	if (b != boxes) {
+		fill.boxes(sna, &fill, boxes, b - boxes);
+		if (damage)
+			sna_damage_add_boxes(damage, boxes, b - boxes, 0, 0);
 	}
 	fill.done(sna, &fill);
 	return TRUE;
@@ -3123,14 +3186,16 @@ sna_poly_line(DrawablePtr drawable, GCPtr gc,
 		    sna_poly_line_blt(drawable,
 				      priv->gpu_bo,
 				      priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, &region.extents),
-				      gc, mode, n, pt, flags & 4))
+				      gc, mode, n, pt,
+				      &region.extents, flags & 4))
 			return;
 
 		if (sna_drawable_use_cpu_bo(drawable, &region.extents) &&
 		    sna_poly_line_blt(drawable,
 				      priv->cpu_bo,
 				      reduce_damage(drawable, &priv->cpu_damage, &region.extents),
-				      gc, mode, n, pt, flags & 4))
+				      gc, mode, n, pt,
+				      &region.extents, flags & 4))
 			return;
 	    } else { /* !rectilinear */
 		if (USE_ZERO_SPANS &&
@@ -3191,133 +3256,205 @@ sna_poly_segment_blt(DrawablePtr drawable,
 		     struct kgem_bo *bo,
 		     struct sna_damage **damage,
 		     GCPtr gc, int n, xSegment *seg,
-		     const BoxRec *extents)
+		     const BoxRec *extents, unsigned clipped)
 {
 	struct sna *sna = to_sna_from_drawable(drawable);
 	PixmapPtr pixmap = get_drawable_pixmap(drawable);
-	RegionRec clip;
+	BoxRec boxes[512], *b = boxes, * const last_box = boxes + ARRAY_SIZE(boxes);
 	struct sna_fill_op fill;
 	int16_t dx, dy;
 
 	DBG(("%s: alu=%d, fg=%08lx\n", __FUNCTION__, gc->alu, gc->fgPixel));
 
-	region_set(&clip, extents);
-	region_maybe_clip(&clip, gc->pCompositeClip);
+	if (!sna_fill_init_blt(&fill, sna, pixmap, bo, gc->alu, gc->fgPixel))
+		return FALSE;
 
-	if (n == 1 && clip.data == NULL) {
-		BoxRec r;
-		int width, height;
-		bool success = true;
+	get_drawable_deltas(drawable, pixmap, &dx, &dy);
 
-		DBG(("%s: trying single fill fast-path\n", __FUNCTION__));
+	if (!clipped) {
+		dx += drawable->x;
+		dy += drawable->y;
+		do {
+			int x, y, width, height;
 
-		if (seg->x1 < seg->x2) {
-			r.x1 = seg->x1;
-			width = seg->x2;
-		} else {
-			r.x1 = seg->x2;
-			width = seg->x1;
-		}
-		width -= r.x1 - 1;
-		r.x1 += drawable->x;
+			if (seg->x1 < seg->x2) {
+				x = seg->x1;
+				width = seg->x2;
+			} else {
+				x = seg->x2;
+				width = seg->x1;
+			}
+			width -= x - 1;
 
-		if (seg->y1 < seg->y2) {
-			r.y1 = seg->y1;
-			height = seg->y2;
-		} else {
-			r.y1 = seg->y2;
-			height = seg->y1;
-		}
-		height -= r.y1- 1;
-		r.y1 += drawable->y;
+			if (seg->y1 < seg->y2) {
+				y = seg->y1;
+				height = seg->y2;
+			} else {
+				y = seg->y2;
+				height = seg->y1;
+			}
+			height -= y - 1;
+
+			/* don't paint last pixel */
+			if (gc->capStyle == CapNotLast) {
+				if (width == 1)
+					height--;
+				else
+					width--;
+			}
 
-		/* don't paint last pixel */
-		if (gc->capStyle == CapNotLast) {
-			if (width == 1)
-				height--;
-			else
-				width--;
-		}
-		r.x2 = r.x1 + width;
-		r.y2 = r.y1 + height;
+			DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
+			     x, y, width, height, dx, dy));
 
-		if (box_intersect(&r, &clip.extents)) {
-			get_drawable_deltas(drawable, pixmap, &dx, &dy);
-			r.x1 += dx; r.y1 += dy;
-			r.x2 += dx; r.y2 += dy;
-			if (sna->render.fill_one(sna, pixmap, bo, gc->fgPixel,
-						 r.x1, r.y1, r.x2, r.y2,
-						 gc->alu)) {
-				if (damage) {
-					assert_pixmap_contains_box(pixmap, &r);
-					sna_damage_add_box(damage, &r);
+			b->x1 = x + dx;
+			b->x2 = b->x1 + width;
+			b->y1 = y + dy;
+			b->y2 = b->y1 + height;
+			if (++b == last_box) {
+				fill.boxes(sna, &fill, boxes, last_box-boxes);
+				if (damage)
+					sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
+				b = boxes;
+			}
+
+			seg++;
+		} while (--n);
+	} else {
+		RegionRec clip;
+
+		region_set(&clip, extents);
+		region_maybe_clip(&clip, gc->pCompositeClip);
+
+		if (!RegionNotEmpty(&clip))
+			goto done;
+
+		if (clip.data) {
+			const BoxRec * const clip_start = RegionBoxptr(&clip);
+			const BoxRec * const clip_end = clip_start + clip.data->numRects;
+			const BoxRec *c;
+			do {
+				int x, y, width, height;
+				BoxRec box;
+
+				if (seg->x1 < seg->x2) {
+					x = seg->x1;
+					width = seg->x2;
+				} else {
+					x = seg->x2;
+					width = seg->x1;
 				}
-			} else
-				success = false;
-		}
+				width -= x - 1;
 
-		return success;
-	}
+				if (seg->y1 < seg->y2) {
+					y = seg->y1;
+					height = seg->y2;
+				} else {
+					y = seg->y2;
+					height = seg->y1;
+				}
+				height -= y - 1;
+
+				/* don't paint last pixel */
+				if (gc->capStyle == CapNotLast) {
+					if (width == 1)
+						height--;
+					else
+						width--;
+				}
 
-	if (!sna_fill_init_blt(&fill, sna, pixmap, bo, gc->alu, gc->fgPixel)) {
-		RegionUninit(&clip);
-		return FALSE;
-	}
+				DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
+				     x, y, width, height, dx+drawable->x, dy+drawable->y));
+				box.x1 = x + drawable->x;
+				box.x2 = box.x1 + width;
+				box.y1 = y + drawable->y;
+				box.y2 = box.y1 + height;
+				c = find_clip_box_for_y(clip_start,
+							clip_end,
+							box.y1);
+				while (c != clip_end) {
+					if (box.y2 <= c->y1)
+						break;
 
-	get_drawable_deltas(drawable, pixmap, &dx, &dy);
-	while (n--) {
-		int x, y, width, height, nclip;
-		BoxPtr box;
+					*b = box;
+					if (box_intersect(b, c)) {
+						b->x1 += dx;
+						b->x2 += dx;
+						b->y1 += dy;
+						b->y2 += dy;
+						if (++b == last_box) {
+							fill.boxes(sna, &fill, boxes, last_box-boxes);
+							if (damage)
+								sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
+							b = boxes;
+						}
+					}
+				}
 
-		if (seg->x1 < seg->x2) {
-			x = seg->x1;
-			width = seg->x2;
+				seg++;
+			} while (--n);
 		} else {
-			x = seg->x2;
-			width = seg->x1;
-		}
-		width -= x - 1;
-		x += drawable->x;
+			do {
+				int x, y, width, height;
 
-		if (seg->y1 < seg->y2) {
-			y = seg->y1;
-			height = seg->y2;
-		} else {
-			y = seg->y2;
-			height = seg->y1;
-		}
-		height -= y - 1;
-		y += drawable->y;
+				if (seg->x1 < seg->x2) {
+					x = seg->x1;
+					width = seg->x2;
+				} else {
+					x = seg->x2;
+					width = seg->x1;
+				}
+				width -= x - 1;
 
-		/* don't paint last pixel */
-		if (gc->capStyle == CapNotLast) {
-			if (width == 1)
-				height--;
-			else
-				width--;
-		}
+				if (seg->y1 < seg->y2) {
+					y = seg->y1;
+					height = seg->y2;
+				} else {
+					y = seg->y2;
+					height = seg->y1;
+				}
+				height -= y - 1;
+
+				/* don't paint last pixel */
+				if (gc->capStyle == CapNotLast) {
+					if (width == 1)
+						height--;
+					else
+						width--;
+				}
 
-		DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
-		     x, y, width, height, dx, dy));
-		for (nclip = REGION_NUM_RECTS(&clip), box = REGION_RECTS(&clip); nclip--; box++) {
-			BoxRec r = { x, y, x + width, y + height };
-			if (box_intersect(&r, box)) {
-				r.x1 += dx;
-				r.x2 += dx;
-				r.y1 += dy;
-				r.y2 += dy;
-				fill.box(sna, &fill, &r);
-				if (damage) {
-					assert_pixmap_contains_box(pixmap, &r);
-					sna_damage_add_box(damage, &r);
+				DBG(("%s: [%d] (%d, %d)x(%d, %d) + (%d, %d)\n", __FUNCTION__, n,
+				     x, y, width, height, dx+drawable->x, dy+drawable->y));
+
+				b->x1 = x + drawable->x;
+				b->x2 = b->x1 + width;
+				b->y1 = y + drawable->y;
+				b->y2 = b->y1 + height;
+
+				if (box_intersect(b, &clip.extents)) {
+					b->x1 += dx;
+					b->x2 += dx;
+					b->y1 += dy;
+					b->y2 += dy;
+					if (++b == last_box) {
+						fill.boxes(sna, &fill, boxes, last_box-boxes);
+						if (damage)
+							sna_damage_add_boxes(damage, boxes, last_box-boxes, 0, 0);
+						b = boxes;
+					}
 				}
-			}
-		}
 
-		seg++;
+				seg++;
+			} while (--n);
+		}
+		RegionUninit(&clip);
+	}
+	if (b != boxes) {
+		fill.boxes(sna, &fill, boxes, b - boxes);
+		if (damage)
+			sna_damage_add_boxes(damage, boxes, b - boxes, 0, 0);
 	}
+done:
 	fill.done(sna, &fill);
-	RegionUninit(&clip);
 	return TRUE;
 }
 
@@ -3744,14 +3881,16 @@ sna_poly_segment(DrawablePtr drawable, GCPtr gc, int n, xSegment *seg)
 		    sna_poly_segment_blt(drawable,
 					 priv->gpu_bo,
 					 priv->gpu_only ? NULL : reduce_damage(drawable, &priv->gpu_damage, &region.extents),
-					 gc, n, seg, &region.extents))
+					 gc, n, seg,
+					 &region.extents, flags & 2))
 			return;
 
 		if (sna_drawable_use_cpu_bo(drawable, &region.extents) &&
 		    sna_poly_segment_blt(drawable,
 					 priv->cpu_bo,
 					 reduce_damage(drawable, &priv->cpu_damage, &region.extents),
-					 gc, n, seg, &region.extents))
+					 gc, n, seg,
+					 &region.extents, flags & 2))
 			return;
 	    } else {
 		    if (USE_ZERO_SPANS &&
commit 5d51ff0cf901b808c3cd5aea761d51e6d15b73bf
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Oct 27 13:57:59 2011 +0100

    sna: Clip PolyLines to the current clip box
    
    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 7b8f761..d776103 100644
--- a/src/sna/sna_accel.c
+++ b/src/sna/sna_accel.c
@@ -2638,7 +2638,7 @@ sna_poly_zero_line_blt(DrawablePtr drawable,
 				b->x2++;
 				b->y2++;
 				if (oc1 | oc2)
-					box_intersect(b, &clip.extents);
+					box_intersect(b, extents);
 				if (++b == last_box) {
 					ret = &&rectangle_continue;
 					goto *jump;
@@ -3431,7 +3431,7 @@ sna_poly_zero_segment_blt(DrawablePtr drawable,
 				b->x2++;
 				b->y2++;
 				if (oc1 | oc2)
-					box_intersect(b, &clip.extents);
+					box_intersect(b, extents);
 				if (++b == last_box) {
 					ret = &&rectangle_continue;
 					goto *jump;


More information about the xorg-commit mailing list