xf86-video-intel: src/sna/sna_trapezoids.h src/sna/sna_trapezoids_imprecise.c src/sna/sna_trapezoids_mono.c src/sna/sna_trapezoids_precise.c

Chris Wilson ickle at kemper.freedesktop.org
Wed Sep 24 00:15:58 PDT 2014


 src/sna/sna_trapezoids.h           |   32 +++
 src/sna/sna_trapezoids_imprecise.c |   23 --
 src/sna/sna_trapezoids_mono.c      |  159 ++++++++++++++++-
 src/sna/sna_trapezoids_precise.c   |  344 ++++++++++++++++++++++++++++++++++++-
 4 files changed, 533 insertions(+), 25 deletions(-)

New commits:
commit 911a0ad8d0520554dc55883997dd59dc3f5f9139
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Sep 24 08:05:01 2014 +0100

    sna/trapezoids: Flesh out alternate rasterisers for tristrips
    
    And undo the accidental commit of
    
    commit 4e00cbe35d1a409a02ee27d991213d9a0807e500
    Author: Chris Wilson <chris at chris-wilson.co.uk>
    Date:   Mon Sep 22 08:54:57 2014 +0100
    
        traps
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_trapezoids.h b/src/sna/sna_trapezoids.h
index 5acf531..e8f7f3f 100644
--- a/src/sna/sna_trapezoids.h
+++ b/src/sna/sna_trapezoids.h
@@ -227,10 +227,37 @@ triangles_mask_converter(CARD8 op, PicturePtr src, PicturePtr dst,
 			 int count, xTriangle *tri);
 
 bool
+mono_tristrip_span_converter(struct sna *sna,
+			     CARD8 op, PicturePtr src, PicturePtr dst,
+			     INT16 src_x, INT16 src_y,
+			     int count, xPointFixed *points);
+bool
+imprecise_tristrip_span_converter(struct sna *sna,
+				  CARD8 op, PicturePtr src, PicturePtr dst,
+				  PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+				  int count, xPointFixed *points);
+bool
+precise_tristrip_span_converter(struct sna *sna,
+				CARD8 op, PicturePtr src, PicturePtr dst,
+				PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+				int count, xPointFixed *points);
+
+static inline bool
 tristrip_span_converter(struct sna *sna,
 			CARD8 op, PicturePtr src, PicturePtr dst,
 			PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
-			int count, xPointFixed *points);
+			int count, xPointFixed *points)
+{
+	if (NO_SCAN_CONVERTER)
+		return false;
+
+	if (is_mono(dst, maskFormat))
+		return mono_tristrip_span_converter(sna, op, src, dst, src_x, src_y, count, points);
+	else if (is_precise(dst, maskFormat))
+		return precise_tristrip_span_converter(sna, op, src, dst, maskFormat, src_x, src_y, count, points);
+	else
+		return imprecise_tristrip_span_converter(sna, op, src, dst, maskFormat, src_x, src_y, count, points);
+}
 
 inline static void trapezoid_origin(const xLineFixed *l, int16_t *x, int16_t *y)
 {
@@ -332,8 +359,7 @@ xTriangleValid(const xTriangle *t)
 
 static inline int pixman_fixed_to_fast(pixman_fixed_t v)
 {
-	//return (v + ((1<<(16-FAST_SAMPLES_shift-1))-1)) >> (16 - FAST_SAMPLES_shift);
-	return (v + ((1<<(16-FAST_SAMPLES_shift-1)))) >> (16 - FAST_SAMPLES_shift);
+	return (v + ((1<<(16-FAST_SAMPLES_shift-1))-1)) >> (16 - FAST_SAMPLES_shift);
 }
 
 bool trapezoids_bounds(int n, const xTrapezoid *t, BoxPtr box);
diff --git a/src/sna/sna_trapezoids_imprecise.c b/src/sna/sna_trapezoids_imprecise.c
index 8bb5426..8230665 100644
--- a/src/sna/sna_trapezoids_imprecise.c
+++ b/src/sna/sna_trapezoids_imprecise.c
@@ -42,7 +42,7 @@
 #undef SAMPLES_X
 #undef SAMPLES_Y
 
-#if 1
+#if 0
 #define __DBG DBG
 #else
 #define __DBG(x)
@@ -633,6 +633,7 @@ polygon_add_line(struct polygon *polygon,
 			unsigned ix = EDGE_Y_BUCKET_INDEX(e->ytop,
 							  polygon->ymin);
 			polygon->y_buckets[ix] = prev->next;
+			polygon->num_edges--;
 			return;
 		}
 	}
@@ -1940,7 +1941,7 @@ imprecise_trapezoid_span_converter(struct sna *sna,
 	dy *= FAST_SAMPLES_Y;
 
 	num_threads = 1;
-	if (!NO_GPU_THREADS && 0 &&
+	if (!NO_GPU_THREADS &&
 	    (flags & COMPOSITE_SPANS_RECTILINEAR) == 0 &&
 	    tmp.thread_boxes &&
 	    thread_choose_span(&tmp, dst, maskFormat, &clip))
@@ -3876,10 +3877,10 @@ tristrip_thread(void *arg)
 }
 
 bool
-tristrip_span_converter(struct sna *sna,
-			CARD8 op, PicturePtr src, PicturePtr dst,
-			PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
-			int count, xPointFixed *points)
+imprecise_tristrip_span_converter(struct sna *sna,
+				  CARD8 op, PicturePtr src, PicturePtr dst,
+				  PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+				  int count, xPointFixed *points)
 {
 	struct sna_composite_spans_op tmp;
 	BoxRec extents;
@@ -3888,16 +3889,6 @@ tristrip_span_converter(struct sna *sna,
 	int dx, dy, num_threads;
 	bool was_clear;
 
-	if (NO_SCAN_CONVERTER)
-		return false;
-
-	/* XXX strict adherence to the Render specification */
-	if (is_precise(dst, maskFormat)) {
-		DBG(("%s: fallback -- precise rasterisation requested\n",
-		     __FUNCTION__));
-		return false;
-	}
-
 	if (!sna->render.check_composite_spans(sna, op, src, dst, 0, 0, 0)) {
 		DBG(("%s: fallback -- composite spans not supported\n",
 		     __FUNCTION__));
diff --git a/src/sna/sna_trapezoids_mono.c b/src/sna/sna_trapezoids_mono.c
index acd2b10..d53e535 100644
--- a/src/sna/sna_trapezoids_mono.c
+++ b/src/sna/sna_trapezoids_mono.c
@@ -356,7 +356,7 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
 	struct mono_edge *e;
 
 	e = edges;
-	do {
+	while (e->next) {
 		struct mono_edge *n = e->next;
 		if (e->dir == -n->dir &&
 		    e->height_left == n->height_left &&
@@ -373,8 +373,8 @@ static struct mono_edge *mono_filter(struct mono_edge *edges)
 
 			e = n->next;
 		} else
-			e = e->next;
-	} while (e->next);
+			e = n;
+	}
 
 	return edges;
 }
@@ -1425,3 +1425,156 @@ mono_triangles_span_converter(struct sna *sna,
 	REGION_UNINIT(NULL, &mono.clip);
 	return true;
 }
+
+bool
+mono_tristrip_span_converter(struct sna *sna,
+			     CARD8 op, PicturePtr src, PicturePtr dst,
+			     INT16 src_x, INT16 src_y,
+			     int count, xPointFixed *points)
+{
+	struct mono mono;
+	BoxRec extents;
+	int16_t dst_x, dst_y;
+	int16_t dx, dy;
+	bool was_clear;
+	int n;
+
+	mono.sna = sna;
+
+	dst_x = pixman_fixed_to_int(points[0].x);
+	dst_y = pixman_fixed_to_int(points[0].y);
+
+	miPointFixedBounds(count, points, &extents);
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, extents.x1, extents.y1, extents.x2, extents.y2));
+
+	if (extents.y1 >= extents.y2 || extents.x1 >= extents.x2)
+		return true;
+
+	if (!sna_compute_composite_region(&mono.clip,
+					  src, NULL, dst,
+					  src_x + extents.x1 - dst_x,
+					  src_y + extents.y1 - dst_y,
+					  0, 0,
+					  extents.x1, extents.y1,
+					  extents.x2 - extents.x1,
+					  extents.y2 - extents.y1)) {
+		DBG(("%s: triangles do not intersect drawable clips\n",
+		     __FUNCTION__)) ;
+		return true;
+	}
+
+	dx = dst->pDrawable->x;
+	dy = dst->pDrawable->y;
+
+	DBG(("%s: after clip -- extents (%d, %d), (%d, %d), delta=(%d, %d) src -> (%d, %d)\n",
+	     __FUNCTION__,
+	     mono.clip.extents.x1, mono.clip.extents.y1,
+	     mono.clip.extents.x2, mono.clip.extents.y2,
+	     dx, dy,
+	     src_x + mono.clip.extents.x1 - dst_x - dx,
+	     src_y + mono.clip.extents.y1 - dst_y - dy));
+
+	was_clear = sna_drawable_is_clear(dst->pDrawable);
+
+	if (!mono_init(&mono, 2*count))
+		return false;
+
+	mono_add_line(&mono, dx, dy,
+		      points[0].y, points[1].y,
+		      &points[0], &points[1], -1);
+	n = 2;
+	do {
+		mono_add_line(&mono, dx, dy,
+			      points[n-2].y, points[n].y,
+			      &points[n-2], &points[n], 1);
+		if (++n == count)
+			break;
+
+		mono_add_line(&mono, dx, dy,
+			      points[n-2].y, points[n].y,
+			      &points[n-2], &points[n], -1);
+		if (++n == count)
+			break;
+	} while (1);
+	mono_add_line(&mono, dx, dy,
+		      points[n-2].y, points[n-1].y,
+		      &points[n-2], &points[n-1], 1);
+
+	if (mono.sna->render.composite(mono.sna, op, src, NULL, dst,
+				       src_x + mono.clip.extents.x1 - dst_x - dx,
+				       src_y + mono.clip.extents.y1 - dst_y - dy,
+				       0, 0,
+				       mono.clip.extents.x1,  mono.clip.extents.y1,
+				       mono.clip.extents.x2 - mono.clip.extents.x1,
+				       mono.clip.extents.y2 - mono.clip.extents.y1,
+				       COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
+		if (mono.clip.data == NULL && mono.op.damage == NULL)
+			mono.span = mono_span__fast;
+		else
+			mono.span = mono_span;
+		mono_render(&mono);
+		mono.op.done(mono.sna, &mono.op);
+	}
+
+	if (!was_clear && !operator_is_bounded(op)) {
+		xPointFixed p1, p2;
+
+		if (!mono_init(&mono, 2+2*count))
+			return false;
+
+		p1.y = mono.clip.extents.y1 * pixman_fixed_1;
+		p2.y = mono.clip.extents.y2 * pixman_fixed_1;
+
+		p1.x = mono.clip.extents.x1 * pixman_fixed_1;
+		p2.x = mono.clip.extents.x1 * pixman_fixed_1;
+		mono_add_line(&mono, 0, 0, p1.y, p2.y, &p1, &p2, -1);
+
+		p1.x = mono.clip.extents.x2 * pixman_fixed_1;
+		p2.x = mono.clip.extents.x2 * pixman_fixed_1;
+		mono_add_line(&mono, 0, 0, p1.y, p2.y, &p1, &p2, 1);
+
+		mono_add_line(&mono, dx, dy,
+			      points[0].y, points[1].y,
+			      &points[0], &points[1], -1);
+		n = 2;
+		do {
+			mono_add_line(&mono, dx, dy,
+				      points[n-2].y, points[n].y,
+				      &points[n-2], &points[n], 1);
+			if (++n == count)
+				break;
+
+			mono_add_line(&mono, dx, dy,
+				      points[n-2].y, points[n].y,
+				      &points[n-2], &points[n], -1);
+			if (++n == count)
+				break;
+		} while (1);
+		mono_add_line(&mono, dx, dy,
+			      points[n-2].y, points[n-1].y,
+			      &points[n-2], &points[n-1], 1);
+
+		if (mono.sna->render.composite(mono.sna,
+					       PictOpClear,
+					       mono.sna->clear, NULL, dst,
+					       0, 0,
+					       0, 0,
+					       mono.clip.extents.x1,  mono.clip.extents.y1,
+					       mono.clip.extents.x2 - mono.clip.extents.x1,
+					       mono.clip.extents.y2 - mono.clip.extents.y1,
+					       COMPOSITE_PARTIAL, memset(&mono.op, 0, sizeof(mono.op)))) {
+			if (mono.clip.data == NULL && mono.op.damage == NULL)
+				mono.span = mono_span__fast;
+			else
+				mono.span = mono_span;
+			mono_render(&mono);
+			mono.op.done(mono.sna, &mono.op);
+		}
+		mono_fini(&mono);
+	}
+
+	mono_fini(&mono);
+	REGION_UNINIT(NULL, &mono.clip);
+	return true;
+}
diff --git a/src/sna/sna_trapezoids_precise.c b/src/sna/sna_trapezoids_precise.c
index 99ed087..af05fe4 100644
--- a/src/sna/sna_trapezoids_precise.c
+++ b/src/sna/sna_trapezoids_precise.c
@@ -663,7 +663,7 @@ static struct edge *filter(struct edge *edges)
 	struct edge *e;
 
 	e = edges;
-	do {
+	while (e->next) {
 		struct edge *n = e->next;
 		if (e->dir == -n->dir &&
 		    e->height_left == n->height_left &&
@@ -680,8 +680,8 @@ static struct edge *filter(struct edge *edges)
 
 			e = n->next;
 		} else
-			e = e->next;
-	} while (e->next);
+			e = n;
+	}
 
 	return edges;
 }
@@ -3238,3 +3238,341 @@ precise_trapezoid_span_fallback(CARD8 op, PicturePtr src, PicturePtr dst,
 
 	return true;
 }
+
+static inline void
+project_point_onto_grid(const xPointFixed *in,
+			int dx, int dy,
+			xPointFixed *out)
+{
+	out->x = dx + pixman_fixed_to_grid_x(in->x);
+	out->y = dy + pixman_fixed_to_grid_y(in->y);
+	__DBG(("%s: (%f, %f) -> (%d, %d)\n",
+	       __FUNCTION__,
+	       pixman_fixed_to_double(in->x),
+	       pixman_fixed_to_double(in->y),
+	       out->x, out->y));
+}
+
+inline static void
+polygon_add_line(struct polygon *polygon,
+		 const xPointFixed *p1,
+		 const xPointFixed *p2)
+{
+	struct edge *e = &polygon->edges[polygon->num_edges];
+	int dx = p2->x - p1->x;
+	int dy = p2->y - p1->y;
+	int top, bot;
+
+	if (dy == 0)
+		return;
+
+	__DBG(("%s: line=(%d, %d), (%d, %d)\n",
+	       __FUNCTION__, (int)p1->x, (int)p1->y, (int)p2->x, (int)p2->y));
+
+	e->dir = 1;
+	if (dy < 0) {
+		const xPointFixed *t;
+
+		dx = -dx;
+		dy = -dy;
+
+		e->dir = -1;
+
+		t = p1;
+		p1 = p2;
+		p2 = t;
+	}
+	assert (dy > 0);
+	e->dy = dy;
+
+	top = MAX(p1->y, polygon->ymin);
+	bot = MIN(p2->y, polygon->ymax);
+	if (bot <= top)
+		return;
+
+	e->ytop = top;
+	e->height_left = bot - top;
+	if (e->height_left <= 0)
+		return;
+
+	__DBG(("%s: edge height=%d\n", __FUNCTION__, e->dir * e->height_left));
+
+	if (dx == 0) {
+		e->x.quo = p1->x;
+		e->x.rem = -dy;
+		e->dxdy.quo = 0;
+		e->dxdy.rem = 0;
+		e->dy = 0;
+	} else {
+		e->dxdy = floored_divrem(dx, dy);
+		if (top == p1->y) {
+			e->x.quo = p1->x;
+			e->x.rem = -dy;
+		} else {
+			e->x = floored_muldivrem(top - p1->y, dx, dy);
+			e->x.quo += p1->x;
+			e->x.rem -= dy;
+		}
+	}
+
+	if (polygon->num_edges > 0) {
+		struct edge *prev = &polygon->edges[polygon->num_edges-1];
+		/* detect degenerate triangles inserted into tristrips */
+		if (e->dir == -prev->dir &&
+		    e->ytop == prev->ytop &&
+		    e->height_left == prev->height_left &&
+		    e->x.quo == prev->x.quo &&
+		    e->x.rem == prev->x.rem &&
+		    e->dxdy.quo == prev->dxdy.quo &&
+		    e->dxdy.rem == prev->dxdy.rem) {
+			unsigned ix = EDGE_Y_BUCKET_INDEX(e->ytop,
+							  polygon->ymin);
+			polygon->y_buckets[ix] = prev->next;
+			polygon->num_edges--;
+			return;
+		}
+	}
+
+	_polygon_insert_edge_into_its_y_bucket(polygon, e);
+	polygon->num_edges++;
+}
+
+struct tristrip_thread {
+	struct sna *sna;
+	const struct sna_composite_spans_op *op;
+	const xPointFixed *points;
+	RegionPtr clip;
+	span_func_t span;
+	BoxRec extents;
+	int dx, dy, draw_y;
+	int count;
+	bool unbounded;
+};
+
+static void
+tristrip_thread(void *arg)
+{
+	struct tristrip_thread *thread = arg;
+	struct span_thread_boxes boxes;
+	struct tor tor;
+	xPointFixed p[4];
+	int n, cw, ccw;
+
+	if (!tor_init(&tor, &thread->extents, 2*thread->count))
+		return;
+
+	boxes.op = thread->op;
+	boxes.num_boxes = 0;
+
+	cw = ccw = 0;
+	project_point_onto_grid(&thread->points[0], thread->dx, thread->dy, &p[cw]);
+	project_point_onto_grid(&thread->points[1], thread->dx, thread->dy, &p[2+ccw]);
+	polygon_add_line(tor.polygon, &p[2+ccw], &p[cw]);
+	n = 2;
+	do {
+		cw = !cw;
+		project_point_onto_grid(&thread->points[n], thread->dx, thread->dy, &p[cw]);
+		polygon_add_line(tor.polygon, &p[!cw], &p[cw]);
+		if (++n == thread->count)
+			break;
+
+		ccw = !ccw;
+		project_point_onto_grid(&thread->points[n], thread->dx, thread->dy, &p[2+ccw]);
+		polygon_add_line(tor.polygon, &p[2+ccw], &p[2+!ccw]);
+		if (++n == thread->count)
+			break;
+	} while (1);
+	polygon_add_line(tor.polygon, &p[cw], &p[2+ccw]);
+	assert(tor.polygon->num_edges <= 2*thread->count);
+
+	tor_render(thread->sna, &tor,
+		   (struct sna_composite_spans_op *)&boxes, thread->clip,
+		   thread->span, thread->unbounded);
+
+	tor_fini(&tor);
+
+	if (boxes.num_boxes) {
+		DBG(("%s: flushing %d boxes\n", __FUNCTION__, boxes.num_boxes));
+		assert(boxes.num_boxes <= SPAN_THREAD_MAX_BOXES);
+		thread->op->thread_boxes(thread->sna, thread->op,
+					 boxes.boxes, boxes.num_boxes);
+	}
+}
+
+bool
+precise_tristrip_span_converter(struct sna *sna,
+				CARD8 op, PicturePtr src, PicturePtr dst,
+				PictFormatPtr maskFormat, INT16 src_x, INT16 src_y,
+				int count, xPointFixed *points)
+{
+	struct sna_composite_spans_op tmp;
+	BoxRec extents;
+	pixman_region16_t clip;
+	int16_t dst_x, dst_y;
+	int dx, dy, num_threads;
+	bool was_clear;
+
+	if (!sna->render.check_composite_spans(sna, op, src, dst, 0, 0, 0)) {
+		DBG(("%s: fallback -- composite spans not supported\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	dst_x = pixman_fixed_to_int(points[0].x);
+	dst_y = pixman_fixed_to_int(points[0].y);
+
+	miPointFixedBounds(count, points, &extents);
+	DBG(("%s: extents (%d, %d), (%d, %d)\n",
+	     __FUNCTION__, extents.x1, extents.y1, extents.x2, extents.y2));
+
+	if (extents.y1 >= extents.y2 || extents.x1 >= extents.x2)
+		return true;
+
+#if 0
+	if (extents.y2 - extents.y1 < 64 && extents.x2 - extents.x1 < 64) {
+		DBG(("%s: fallback -- traps extents too small %dx%d\n",
+		     __FUNCTION__, extents.y2 - extents.y1, extents.x2 - extents.x1));
+		return false;
+	}
+#endif
+
+	if (!sna_compute_composite_region(&clip,
+					  src, NULL, dst,
+					  src_x + extents.x1 - dst_x,
+					  src_y + extents.y1 - dst_y,
+					  0, 0,
+					  extents.x1, extents.y1,
+					  extents.x2 - extents.x1,
+					  extents.y2 - extents.y1)) {
+		DBG(("%s: triangles do not intersect drawable clips\n",
+		     __FUNCTION__)) ;
+		return true;
+	}
+
+	if (!sna->render.check_composite_spans(sna, op, src, dst,
+					       clip.extents.x2 - clip.extents.x1,
+					       clip.extents.y2 - clip.extents.y1,
+					       0)) {
+		DBG(("%s: fallback -- composite spans not supported\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	extents = *RegionExtents(&clip);
+	dx = dst->pDrawable->x;
+	dy = dst->pDrawable->y;
+
+	DBG(("%s: after clip -- extents (%d, %d), (%d, %d), delta=(%d, %d) src -> (%d, %d)\n",
+	     __FUNCTION__,
+	     extents.x1, extents.y1,
+	     extents.x2, extents.y2,
+	     dx, dy,
+	     src_x + extents.x1 - dst_x - dx,
+	     src_y + extents.y1 - dst_y - dy));
+
+	was_clear = sna_drawable_is_clear(dst->pDrawable);
+
+	memset(&tmp, 0, sizeof(tmp));
+	if (!sna->render.composite_spans(sna, op, src, dst,
+					 src_x + extents.x1 - dst_x - dx,
+					 src_y + extents.y1 - dst_y - dy,
+					 extents.x1,  extents.y1,
+					 extents.x2 - extents.x1,
+					 extents.y2 - extents.y1,
+					 0,
+					 &tmp)) {
+		DBG(("%s: fallback -- composite spans render op not supported\n",
+		     __FUNCTION__));
+		return false;
+	}
+
+	dx *= SAMPLES_X;
+	dy *= SAMPLES_Y;
+
+	num_threads = 1;
+	if (!NO_GPU_THREADS && 0 &&
+	    tmp.thread_boxes &&
+	    thread_choose_span(&tmp, dst, maskFormat, &clip))
+		num_threads = sna_use_threads(extents.x2 - extents.x1,
+					      extents.y2 - extents.y1,
+					      16);
+	if (num_threads == 1) {
+		struct tor tor;
+		xPointFixed p[4];
+		int cw, ccw, n;
+
+		if (!tor_init(&tor, &extents, 2*count))
+			goto skip;
+
+		cw = ccw = 0;
+		project_point_onto_grid(&points[0], dx, dy, &p[cw]);
+		project_point_onto_grid(&points[1], dx, dy, &p[2+ccw]);
+		polygon_add_line(tor.polygon, &p[2+ccw], &p[cw]);
+		n = 2;
+		do {
+			cw = !cw;
+			project_point_onto_grid(&points[n], dx, dy, &p[cw]);
+			polygon_add_line(tor.polygon, &p[!cw], &p[cw]);
+			if (++n == count)
+				break;
+
+			ccw = !ccw;
+			project_point_onto_grid(&points[n], dx, dy, &p[2+ccw]);
+			polygon_add_line(tor.polygon, &p[2+ccw], &p[2+!ccw]);
+			if (++n == count)
+				break;
+		} while (1);
+		polygon_add_line(tor.polygon, &p[cw], &p[2+ccw]);
+		assert(tor.polygon->num_edges <= 2*count);
+
+		tor_render(sna, &tor, &tmp, &clip,
+			   choose_span(&tmp, dst, maskFormat, &clip),
+			   !was_clear && maskFormat && !operator_is_bounded(op));
+
+		tor_fini(&tor);
+	} else {
+		struct tristrip_thread threads[num_threads];
+		int y, h, n;
+
+		DBG(("%s: using %d threads for tristrip compositing %dx%d\n",
+		     __FUNCTION__, num_threads,
+		     clip.extents.x2 - clip.extents.x1,
+		     clip.extents.y2 - clip.extents.y1));
+
+		threads[0].sna = sna;
+		threads[0].op = &tmp;
+		threads[0].points = points;
+		threads[0].count = count;
+		threads[0].extents = clip.extents;
+		threads[0].clip = &clip;
+		threads[0].dx = dx;
+		threads[0].dy = dy;
+		threads[0].draw_y = dst->pDrawable->y;
+		threads[0].unbounded = !was_clear && maskFormat && !operator_is_bounded(op);
+		threads[0].span = thread_choose_span(&tmp, dst, maskFormat, &clip);
+
+		y = clip.extents.y1;
+		h = clip.extents.y2 - clip.extents.y1;
+		h = (h + num_threads - 1) / num_threads;
+		num_threads -= (num_threads-1) * h >= clip.extents.y2 - clip.extents.y1;
+
+		for (n = 1; n < num_threads; n++) {
+			threads[n] = threads[0];
+			threads[n].extents.y1 = y;
+			threads[n].extents.y2 = y += h;
+
+			sna_threads_run(n, tristrip_thread, &threads[n]);
+		}
+
+		assert(y < threads[0].extents.y2);
+		threads[0].extents.y1 = y;
+		tristrip_thread(&threads[0]);
+
+		sna_threads_wait();
+	}
+skip:
+	tmp.done(sna, &tmp);
+
+	REGION_UNINIT(NULL, &clip);
+	return true;
+}


More information about the xorg-commit mailing list