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

Chris Wilson ickle at kemper.freedesktop.org
Mon Oct 7 02:26:25 PDT 2013


 src/sna/sna_trapezoids_imprecise.c |   87 +++++++++---------------------------
 src/sna/sna_trapezoids_precise.c   |   88 ++++++++++---------------------------
 2 files changed, 47 insertions(+), 128 deletions(-)

New commits:
commit d462475b7ecca6eb001b521185d2f7286031a8d8
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Oct 7 10:04:15 2013 +0100

    sna/trapezoids: Fix overstepping vertical edges
    
    Regression from
    
    commit c98b770a87a5ec5ed9dc0aa375ad173b0e98322e
    Author: Chris Wilson <chris at chris-wilson.co.uk>
    Date:   Fri Oct 4 18:37:01 2013 +0100
    
        sna/trapezoids: Add a precise scan converter
    
    Reported-by: Joseph Yasi <joe.yasi at gmail.com>
    Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=70204
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/sna/sna_trapezoids_imprecise.c b/src/sna/sna_trapezoids_imprecise.c
index bbb7f2f..2cfab80 100644
--- a/src/sna/sna_trapezoids_imprecise.c
+++ b/src/sna/sna_trapezoids_imprecise.c
@@ -248,13 +248,6 @@ struct cell_list {
 struct active_list {
 	/* Leftmost edge on the current scan line. */
 	struct edge head, tail;
-
-	/* A lower bound on the height of the active edges is used to
-	 * estimate how soon some active edge ends.	 We can't advance the
-	 * scan conversion by a full pixel row if an edge ends somewhere
-	 * within it. */
-	int min_height;
-	int is_vertical;
 };
 
 struct tor {
@@ -663,8 +656,6 @@ active_list_reset(struct active_list *active)
 	active->tail.x.quo = INT_MAX;
 	active->tail.height_left = INT_MAX;
 	active->tail.dy = 0;
-	active->min_height = INT_MAX;
-	active->is_vertical = 1;
 }
 
 static struct edge *
@@ -788,35 +779,30 @@ merge_unsorted_edges(struct edge *head, struct edge *unsorted)
 inline static bool
 can_full_step(struct active_list *active)
 {
-	/* Recomputes the minimum height of all edges on the active
-	 * list if we have been dropping edges. */
-	if (active->min_height <= 0) {
-		const struct edge *e;
-		int min_height = INT_MAX;
-		int is_vertical = 1;
-
-		for (e = active->head.next; &active->tail != e; e = e->next) {
-			if (e->height_left < min_height)
-				min_height = e->height_left;
-			if (is_vertical)
-				is_vertical = e->dy == 0;
-		}
+	const struct edge *e;
+	int min_height = INT_MAX;
 
-		active->is_vertical = is_vertical;
-		active->min_height = min_height;
-	}
+	assert(active->head.next != &active->tail);
+	for (e = active->head.next; &active->tail != e; e = e->next) {
+		assert(e->height_left >= 0);
 
-	if (active->min_height < FAST_SAMPLES_Y)
-		return false;
+		if (e->dy != 0)
+			return 0;
+
+		if (e->height_left < min_height) {
+			min_height = e->height_left;
+			if (min_height < FAST_SAMPLES_Y)
+				return 0;
+		}
+	}
 
-	return active->is_vertical;
+	return min_height;
 }
 
 inline static void
 merge_edges(struct active_list *active, struct edge *edges)
 {
 	active->head.next = merge_unsorted_edges(active->head.next, edges);
-	active->min_height = -1;
 }
 
 inline static void
@@ -824,9 +810,6 @@ fill_buckets(struct active_list *active,
 	     struct edge *edge,
 	     struct edge **buckets)
 {
-	int min_height = active->min_height;
-	int is_vertical = active->is_vertical;
-
 	while (edge) {
 		struct edge *next = edge->next;
 		struct edge **b = &buckets[edge->ytop & (FAST_SAMPLES_Y-1)];
@@ -835,15 +818,8 @@ fill_buckets(struct active_list *active,
 		edge->next = *b;
 		edge->prev = NULL;
 		*b = edge;
-		if (edge->height_left < min_height)
-			min_height = edge->height_left;
-		if (is_vertical)
-			is_vertical = edge->dy == 0;
 		edge = next;
 	}
-
-	active->is_vertical = is_vertical;
-	active->min_height = min_height;
 }
 
 inline static void
@@ -902,13 +878,12 @@ nonzero_row(struct active_list *active, struct cell_list *coverages)
 {
 	struct edge *left = active->head.next;
 
-	assert(active->is_vertical);
-
 	while (&active->tail != left) {
 		struct edge *right;
 		int winding = left->dir;
 
 		left->height_left -= FAST_SAMPLES_Y;
+		assert(left->height_left >= 0);
 		if (! left->height_left) {
 			left->prev->next = left->next;
 			left->next->prev = left->prev;
@@ -917,6 +892,7 @@ nonzero_row(struct active_list *active, struct cell_list *coverages)
 		right = left->next;
 		do {
 			right->height_left -= FAST_SAMPLES_Y;
+			assert(right->height_left >= 0);
 			if (!right->height_left) {
 				right->prev->next = right->next;
 				right->next->prev = right->prev;
@@ -1224,8 +1200,6 @@ tor_render(struct sna *sna,
 		 * stepper. */
 		if (!polygon->y_buckets[i]) {
 			if (active->head.next == &active->tail) {
-				active->min_height = INT_MAX;
-				active->is_vertical = 1;
 				for (; !polygon->y_buckets[j]; j++)
 					;
 				__DBG(("%s: no new edges and no exisiting edges, skipping, %d -> %d\n",
@@ -1242,16 +1216,13 @@ tor_render(struct sna *sna,
 		__DBG(("%s: y=%d [%d], do_full_step=%d, new edges=%d, min_height=%d, vertical=%d\n",
 		       __FUNCTION__,
 		       i, i+ymin, do_full_step,
-		       polygon->y_buckets[i] != NULL,
-		       active->min_height,
-		       active->is_vertical));
+		       polygon->y_buckets[i] != NULL));
 		if (do_full_step) {
-			assert(active->is_vertical);
 			nonzero_row(active, coverages);
 
 			while (polygon->y_buckets[j] == NULL &&
-			       active->min_height >= FAST_SAMPLES_Y) {
-				active->min_height -= FAST_SAMPLES_Y;
+			       do_full_step >= 2*FAST_SAMPLES_Y) {
+				do_full_step -= FAST_SAMPLES_Y;
 				j++;
 			}
 			if (j != i + 1)
@@ -1279,8 +1250,6 @@ tor_render(struct sna *sna,
 			i+ymin, j-i, xmin, xmax,
 			unbounded);
 		cell_list_reset(coverages);
-
-		active->min_height -= FAST_SAMPLES_Y;
 	}
 }
 
@@ -1289,8 +1258,6 @@ inplace_row(struct active_list *active, uint8_t *row, int width)
 {
 	struct edge *left = active->head.next;
 
-	assert(active->is_vertical);
-
 	while (&active->tail != left) {
 		struct edge *right;
 		int winding = left->dir;
@@ -1583,8 +1550,6 @@ tor_inplace(struct tor *converter, PixmapPtr scratch, int mono, uint8_t *buf)
 		 * stepper. */
 		if (!polygon->y_buckets[i]) {
 			if (active->head.next == &active->tail) {
-				active->min_height = INT_MAX;
-				active->is_vertical = 1;
 				for (; !polygon->y_buckets[j]; j++)
 					;
 				__DBG(("%s: no new edges and no exisiting edges, skipping, %d -> %d\n",
@@ -1601,21 +1566,16 @@ tor_inplace(struct tor *converter, PixmapPtr scratch, int mono, uint8_t *buf)
 		__DBG(("%s: y=%d, do_full_step=%d, new edges=%d, min_height=%d, vertical=%d\n",
 		       __FUNCTION__,
 		       i, do_full_step,
-		       polygon->y_buckets[i] != NULL,
-		       active->min_height,
-		       active->is_vertical));
+		       polygon->y_buckets[i] != NULL));
 		if (do_full_step) {
-			assert(active->is_vertical);
-
 			memset(ptr, 0, width);
 			inplace_row(active, ptr, width);
 			if (row != ptr)
 				memcpy(row, ptr, width);
 
 			while (polygon->y_buckets[j] == NULL &&
-			       active->min_height >= FAST_SAMPLES_Y)
-			{
-				active->min_height -= FAST_SAMPLES_Y;
+			       do_full_step >= 2*FAST_SAMPLES_Y) {
+				do_full_step -= FAST_SAMPLES_Y;
 				row += stride;
 				memcpy(row, ptr, width);
 				j++;
@@ -1648,7 +1608,6 @@ tor_inplace(struct tor *converter, PixmapPtr scratch, int mono, uint8_t *buf)
 				memset(row+max, 0, width-max);
 		}
 
-		active->min_height -= FAST_SAMPLES_Y;
 		row += stride;
 	}
 }
diff --git a/src/sna/sna_trapezoids_precise.c b/src/sna/sna_trapezoids_precise.c
index e7a5578..345922f 100644
--- a/src/sna/sna_trapezoids_precise.c
+++ b/src/sna/sna_trapezoids_precise.c
@@ -261,13 +261,6 @@ struct cell_list {
 struct active_list {
 	/* Leftmost edge on the current scan line. */
 	struct edge head, tail;
-
-	/* A lower bound on the height of the active edges is used to
-	 * estimate how soon some active edge ends.	 We can't advance the
-	 * scan conversion by a full pixel row if an edge ends somewhere
-	 * within it. */
-	int min_height;
-	int is_vertical;
 };
 
 struct tor {
@@ -668,8 +661,6 @@ active_list_reset(struct active_list *active)
 	active->tail.x.quo = INT_MAX;
 	active->tail.height_left = INT_MAX;
 	active->tail.dy = 0;
-	active->min_height = INT_MAX;
-	active->is_vertical = 1;
 }
 
 static struct edge *
@@ -793,35 +784,30 @@ merge_unsorted_edges(struct edge *head, struct edge *unsorted)
 inline static bool
 can_full_step(struct active_list *active)
 {
-	/* Recomputes the minimum height of all edges on the active
-	 * list if we have been dropping edges. */
-	if (active->min_height <= 0) {
-		const struct edge *e;
-		int min_height = INT_MAX;
-		int is_vertical = 1;
-
-		for (e = active->head.next; &active->tail != e; e = e->next) {
-			if (e->height_left < min_height)
-				min_height = e->height_left;
-			if (is_vertical)
-				is_vertical = e->dy == 0;
-		}
+	const struct edge *e;
+	int min_height = INT_MAX;
 
-		active->is_vertical = is_vertical;
-		active->min_height = min_height;
-	}
+	assert(active->head.next != &active->tail);
+	for (e = active->head.next; &active->tail != e; e = e->next) {
+		assert(e->height_left >= 0);
 
-	if (active->min_height < SAMPLES_Y)
-		return false;
+		if (e->dy != 0)
+			return 0;
+
+		if (e->height_left < min_height) {
+			min_height = e->height_left;
+			if (min_height < SAMPLES_Y)
+				return 0;
+		}
+	}
 
-	return active->is_vertical;
+	return min_height;
 }
 
 inline static void
 merge_edges(struct active_list *active, struct edge *edges)
 {
 	active->head.next = merge_unsorted_edges(active->head.next, edges);
-	active->min_height = -1;
 }
 
 inline static void
@@ -830,9 +816,6 @@ fill_buckets(struct active_list *active,
 	     int ymin,
 	     struct edge **buckets)
 {
-	int min_height = active->min_height;
-	int is_vertical = active->is_vertical;
-
 	while (edge) {
 		struct edge *next = edge->next;
 		struct edge **b = &buckets[edge->ytop - ymin];
@@ -841,15 +824,8 @@ fill_buckets(struct active_list *active,
 		edge->next = *b;
 		edge->prev = NULL;
 		*b = edge;
-		if (edge->height_left < min_height)
-			min_height = edge->height_left;
-		if (is_vertical)
-			is_vertical = edge->dy == 0;
 		edge = next;
 	}
-
-	active->is_vertical = is_vertical;
-	active->min_height = min_height;
 }
 
 inline static void
@@ -908,13 +884,12 @@ nonzero_row(struct active_list *active, struct cell_list *coverages)
 {
 	struct edge *left = active->head.next;
 
-	assert(active->is_vertical);
-
 	while (&active->tail != left) {
 		struct edge *right;
 		int winding = left->dir;
 
 		left->height_left -= SAMPLES_Y;
+		assert(left->height_left >= 0);
 		if (!left->height_left) {
 			left->prev->next = left->next;
 			left->next->prev = left->prev;
@@ -923,6 +898,7 @@ nonzero_row(struct active_list *active, struct cell_list *coverages)
 		right = left->next;
 		do {
 			right->height_left -= SAMPLES_Y;
+			assert(right->height_left >= 0);
 			if (!right->height_left) {
 				right->prev->next = right->next;
 				right->next->prev = right->prev;
@@ -1181,8 +1157,6 @@ tor_render(struct sna *sna,
 		 * stepper. */
 		if (!polygon->y_buckets[i]) {
 			if (active->head.next == &active->tail) {
-				active->min_height = INT_MAX;
-				active->is_vertical = 1;
 				for (; !polygon->y_buckets[j]; j++)
 					;
 				__DBG(("%s: no new edges and no exisiting edges, skipping, %d -> %d\n",
@@ -1196,19 +1170,16 @@ tor_render(struct sna *sna,
 			do_full_step = can_full_step(active);
 		}
 
-		__DBG(("%s: y=%d [%d], do_full_step=%d, new edges=%d, min_height=%d, vertical=%d\n",
+		__DBG(("%s: y=%d [%d], do_full_step=%d, new edges=%d\n",
 		       __FUNCTION__,
 		       i, i+ymin, do_full_step,
-		       polygon->y_buckets[i] != NULL,
-		       active->min_height,
-		       active->is_vertical));
+		       polygon->y_buckets[i] != NULL));
 		if (do_full_step) {
-			assert(active->is_vertical);
 			nonzero_row(active, coverages);
 
 			while (polygon->y_buckets[j] == NULL &&
-			       active->min_height >= SAMPLES_Y) {
-				active->min_height -= SAMPLES_Y;
+			       do_full_step >= 2*SAMPLES_Y) {
+				do_full_step -= SAMPLES_Y;
 				j++;
 			}
 			if (j != i + 1)
@@ -1236,8 +1207,6 @@ tor_render(struct sna *sna,
 			i+ymin, j-i, xmin, xmax,
 			unbounded);
 		cell_list_reset(coverages);
-
-		active->min_height -= SAMPLES_Y;
 	}
 }
 
@@ -1246,8 +1215,6 @@ inplace_row(struct active_list *active, uint8_t *row, int width)
 {
 	struct edge *left = active->head.next;
 
-	assert(active->is_vertical);
-
 	while (&active->tail != left) {
 		struct edge *right;
 		int winding = left->dir;
@@ -1528,8 +1495,6 @@ tor_inplace(struct tor *converter, PixmapPtr scratch)
 		 * stepper. */
 		if (!polygon->y_buckets[i]) {
 			if (active->head.next == &active->tail) {
-				active->min_height = INT_MAX;
-				active->is_vertical = 1;
 				for (; !polygon->y_buckets[j]; j++)
 					;
 				__DBG(("%s: no new edges and no exisiting edges, skipping, %d -> %d\n",
@@ -1546,20 +1511,16 @@ tor_inplace(struct tor *converter, PixmapPtr scratch)
 		__DBG(("%s: y=%d, do_full_step=%d, new edges=%d, min_height=%d, vertical=%d\n",
 		       __FUNCTION__,
 		       i, do_full_step,
-		       polygon->y_buckets[i] != NULL,
-		       active->min_height,
-		       active->is_vertical));
+		       polygon->y_buckets[i] != NULL));
 		if (do_full_step) {
-			assert(active->is_vertical);
-
 			memset(ptr, 0, width);
 			inplace_row(active, ptr, width);
 			if (row != ptr)
 				memcpy(row, ptr, width);
 
 			while (polygon->y_buckets[j] == NULL &&
-			       active->min_height >= SAMPLES_Y) {
-				active->min_height -= SAMPLES_Y;
+			       do_full_step >= 2*SAMPLES_Y) {
+				do_full_step -= SAMPLES_Y;
 				row += stride;
 				memcpy(row, ptr, width);
 				j++;
@@ -1588,7 +1549,6 @@ tor_inplace(struct tor *converter, PixmapPtr scratch)
 				memcpy(row, ptr, width);
 		}
 
-		active->min_height -= SAMPLES_Y;
 		row += stride;
 	}
 }


More information about the xorg-commit mailing list