summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSøren Sandmann Pedersen <ssp@redhat.com>2011-02-06 15:54:48 -0500
committerSøren Sandmann Pedersen <ssp@redhat.com>2011-06-01 09:23:45 -0400
commit2875048b194b86fd5b9ed1cd326f8b9fa0b86789 (patch)
tree19c351f472a18bbf56f125b364c9d657255d65b3
parent85477e42db11d090cfe5ba6a767207962d207e85 (diff)
Some classification
-rw-r--r--pixman/pixman-polygon.c140
-rw-r--r--test/polygon-small.c4
2 files changed, 138 insertions, 6 deletions
diff --git a/pixman/pixman-polygon.c b/pixman/pixman-polygon.c
index c75a6143..84250bef 100644
--- a/pixman/pixman-polygon.c
+++ b/pixman/pixman-polygon.c
@@ -67,6 +67,8 @@
* +--------------------------------------------------+
*/
+#define force_inline
+
#define POLY_N_Y_FRAC(n) ((n) == 1 ? 1 : (1 << ((n)/2)) - 1)
#define POLY_N_X_FRAC(n) ((n) == 1 ? 1 : (1 << ((n)/2)) + 1)
@@ -272,6 +274,7 @@ struct active_t
uint32_t * buffer;
uint32_t dirty[(((MAX_WIDTH + 15)/ 16) + 31)/32];
int n_edges;
+ uint32_t classification;
edge_t edges[16];
};
@@ -513,7 +516,15 @@ edge_init (edge_t *edge, const pixman_segment_24_8_t *segment,
edge->dy = dy;
edge->dx = dx;
+
+#if 0
+ if (edge->dx < 0)
+ edge->dxdy = - (((- dx) << 32) / dy);
+ else
+ edge->dxdy = (dx << 32) / dy;
+#endif
edge->dxdy = ((((dx < 0)? (-dx) : (dx))) << 32) / dy;
+
edge->e = 0;
#ifdef PRINT_DEBUG_SPEW
@@ -541,8 +552,9 @@ update_active (active_t *active)
edge_t *edge;
active_t *new;
- if (active->global_next->line.p1.x < active->x + active->width ||
- active->global_next->line.p2.x < active->x + active->width)
+ if ((active->global_next->line.p1.x < active->x + active->width ||
+ active->global_next->line.p2.x < active->x + active->width) &&
+ active->global_next->bottom > active->yi)
{
if (!(new = allocate_edge (active, &edge)))
{
@@ -561,6 +573,9 @@ update_active (active_t *active)
active->strategy->big_step);
list_append (active, edge);
+#if 0
+ printf ("New edge: %p\n", edge);
+#endif
}
}
@@ -582,7 +597,9 @@ oom_bail:
if (edge->bottom <= active->yi)
{
#ifdef PRINT_DEBUG_SPEW
- printf ("death %p\n", edge);
+#endif
+#if 0
+ printf ("Dead edge %p\n", edge);
#endif
list_remove (active, edge);
free_edge (active, edge);
@@ -598,7 +615,12 @@ oom_bail:
}
if (k != edge->prev)
+ {
+#if 0
+ printf ("Intersecting edge: %p\n", edge);
+#endif
move_after (active, edge, k);
+ }
}
i = next;
@@ -628,6 +650,102 @@ oom_bail:
printf ("line %f\n", pixman_fixed_24_8_to_double (active->yi));
#endif
+ if ((active->yi & 0xff) == active->strategy->y_frac_first)
+ {
+ uint32_t flags = 0;
+ pixman_fixed_24_8_t next = active->yi + pixman_fixed_24_8_1;
+ edge_t *prev = NULL;
+
+#if 0
+ printf ("New scanline - classifying the state here (0x%x)\n", active->yi);
+#endif
+
+#define DYING_EDGES (1 << 0)
+#define NEW_EDGES (1 << 1)
+#define POTENTIAL_INTERSECTION (1 << 2)
+#define NON_VERTICAL (1 << 3)
+#define NEW_SURVIVORS (1 << 4)
+
+ for (i = active->head; i != -1; i = active->edges[i].next)
+ {
+ edge_t *edge = &(active->edges[i]);
+
+ if (edge->bottom < next)
+ flags |= DYING_EDGES;
+
+ if (prev)
+ {
+ int ps, ts;
+ int y;
+
+ y = prev->bottom;
+ if (edge->bottom < y)
+ y = edge->bottom;
+ if (y > next)
+ y = next;
+ y -= active->yi;
+
+ if (prev->dx < 0)
+ ps = - ((y * prev->dxdy) >> 32);
+ else
+ ps = (y * prev->dxdy) >> 32;
+
+ if (edge->dx < 0)
+ ts = - ((y * edge->dxdy) >> 32);
+ else
+ ts = (y * edge->dxdy >> 32);
+
+ if (edge->x + ts < prev->x + ps)
+ {
+ flags |= POTENTIAL_INTERSECTION;
+#if 0
+ printf ("%p and %p may intersect\n", edge, prev);
+#endif
+ }
+ }
+
+ if (edge->dxdy != 0)
+ flags |= NON_VERTICAL;
+
+ prev = edge;
+
+ active->classification = flags;
+ }
+
+ const pixman_segment_24_8_t *g;
+
+ for (g = active->global_next; g != active->global_last; g++)
+ {
+ if (g->top >= next)
+ break;
+
+ flags |= NEW_EDGES;
+ if (g->bottom > next)
+ flags |= NEW_SURVIVORS;
+ }
+
+ if (flags & NON_VERTICAL)
+ {
+ printf ("Classification: %d %c %c %c %c %c\n",
+ active->n_edges,
+ (flags & NEW_EDGES)? 'N' : ' ',
+ (flags & NEW_SURVIVORS)? 'S' : ' ',
+ (flags & DYING_EDGES)? 'D' : ' ',
+ (flags & POTENTIAL_INTERSECTION)? 'I' : ' ',
+ (!(flags & NON_VERTICAL))? 'V' : ' ');
+ }
+#if 0
+ if ((flags & NEW_EDGES))
+ printf ("- New edges may arrive\n");
+ if ((flags & DYING_EDGES))
+ printf ("- Some edges may die\n");
+ if ((flags & POTENTIAL_INTERSECTION))
+ printf ("- Edges may intersect\n");
+ if (!(flags & NON_VERTICAL))
+ printf ("- All edges are vertical\n");
+#endif
+ }
+
return active;
}
@@ -644,6 +762,10 @@ create_active (polygon_t *polygon, pixman_iter_t *iter)
width = iter->width;
height = iter->height;
+#if 0
+ printf ("new polygon\n");
+#endif
+
#ifdef PRINT_DEBUG_SPEW
printf ("x y %d %d\n", x, y);
#endif
@@ -754,6 +876,10 @@ step_active_inline (active_t *active, int offset, uint winding_mask, uint32_t *d
unsigned winding = 0;
int i;
+#if 0
+ printf ("Active: %d (%x)\n", active->n_edges, active->yi);
+#endif
+
for (i = active->head; i != -1; i = active->edges[i].next)
{
edge_t *edge = &(active->edges[i]);
@@ -799,7 +925,9 @@ step_active (active_t *active, pixman_fixed_24_8_t step_size, uint32_t *dirty)
active->yi += step_size;
- return update_active (active);
+ active = update_active (active);
+
+ return active;
}
static uint32_t *
@@ -811,6 +939,10 @@ polygon_get_scanline_narrow (pixman_iter_t *iter, const uint32_t *mask)
uint32_t acc;
int i, j;
+#if 0
+ printf ("Get scanline\n");
+#endif
+
n_dirty_words = ((iter->width + 15) / 16 + 31) / 32;
for (i = 0; i < n_dirty_words; ++i)
diff --git a/test/polygon-small.c b/test/polygon-small.c
index da6706de..29cd6d90 100644
--- a/test/polygon-small.c
+++ b/test/polygon-small.c
@@ -134,7 +134,7 @@ test_polygon (int testnum,
assert (dst_img);
- image_endian_swap (dst_img, dst_bpp * 8);
+ image_endian_swap (dst_img);
if (verbose)
{
@@ -184,7 +184,7 @@ test_polygon (int testnum,
dstbuf[i] &= 0xFFFFFF;
}
- image_endian_swap (dst_img, dst_bpp * 8);
+ image_endian_swap (dst_img);
if (verbose)
{