PicoVector: Faster polygon rendering.

pull/1019/head
Mike Bell 2025-03-18 18:51:06 +00:00 zatwierdzone przez Phil Howard
rodzic 12228c4036
commit d84a1e3470
1 zmienionych plików z 73 dodań i 48 usunięć

Wyświetl plik

@ -488,45 +488,44 @@ void add_line_segment_to_nodes(const pp_point_t start, const pp_point_t end, pp_
x += xinc * xjump;
}
// #ifdef USE_RP2040_INTERP
// interp1->base[1] = full_tile_width;
// interp1->accum[0] = x;
int32_t *pp_scanline_nodes = &pp_nodes[y * _pp_max_nodes_per_scanline * 2];
const int32_t nodes_step = _pp_max_nodes_per_scanline * 2;
// // loop over scanlines
// while(count--) {
// // consume accumulated error
// while(e > dy) {e -= dy; interp1->add_raw[0] = xinc;}
const int full_tile_width = (tb->w << _pp_antialias);
if (false && _pp_min(x, ex) >= 0 && _pp_max(x, ex) <= full_tile_width) {
// loop over scanlines
while(count--) {
// consume accumulated error
while(e > dy) {e -= dy; x += xinc;}
// // clamp node x value to tile bounds
// const int nx = interp1->peek[0];
// debug(" + adding node at %d, %d\n", x, y);
// // add node to node list
// pp_nodes[y][pp_node_counts[y]++] = nx;
//debug(" + adding node at %d, %d\n", x, y);
// add node to node list
pp_scanline_nodes[pp_node_counts[y]++] = x;
// // step to next scanline and accumulate error
// y++;
// e += einc;
// }
// #else
// loop over scanlines
while(count--) {
int32_t *pp_scanline_nodes = &pp_nodes[y * _pp_max_nodes_per_scanline * 2];
// consume accumulated error
while(e > dy) {e -= dy; x += xinc;}
// clamp node x value to tile bounds
int nx = _pp_max(_pp_min(x, (tb->w << _pp_antialias)), 0);
//debug(" + adding node at %d, %d\n", x, y);
// add node to node list
pp_scanline_nodes[pp_node_counts[y]++] = nx;
// step to next scanline and accumulate error
y++;
e += einc;
// step to next scanline and accumulate error
y++;
e += einc;
pp_scanline_nodes += nodes_step;
}
}
else {
// loop over scanlines
while(count--) {
// consume accumulated error
while(e > dy) {e -= dy; x += xinc;}
// clamp node x value to tile bounds
int nx = _pp_max(_pp_min(x, full_tile_width), 0);
//debug(" + adding node at %d, %d\n", x, y);
// add node to node list
pp_scanline_nodes[pp_node_counts[y]++] = nx;
// step to next scanline and accumulate error
y++;
e += einc;
pp_scanline_nodes += nodes_step;
}
}
//#endif
}
void build_nodes(pp_path_t *path, pp_rect_t *tb) {
@ -555,8 +554,9 @@ int compare_nodes(const void* a, const void* b) {
}
pp_rect_t render_nodes(pp_rect_t *tb) {
pp_rect_t rb = {PP_TILE_BUFFER_SIZE << _pp_antialias, PP_TILE_BUFFER_SIZE << _pp_antialias, 0, 0}; // render bounds
int maxx = 0, minx = PP_TILE_BUFFER_SIZE << _pp_antialias;
pp_rect_t rb = {PP_TILE_BUFFER_SIZE << _pp_antialias, 0, 0, 0}; // render bounds
int maxx = 0, maxy = -1;
const int antialias_mask = (1 << _pp_antialias) - 1;
debug(" + render tile %d, %d - %d, %d\n", tb->x, tb->y, tb->w, tb->h);
for(int y = 0; y < ((int)PP_TILE_BUFFER_SIZE << _pp_antialias); y++) {
@ -570,6 +570,9 @@ pp_rect_t render_nodes(pp_rect_t *tb) {
unsigned char* row_data = &pp_tile_buffer[(y >> _pp_antialias) * PP_TILE_BUFFER_SIZE];
bool rendered_any = false;
rb.x = _pp_min(rb.x, *pp_scanline_nodes);
for(uint32_t i = 0; i < pp_node_counts[y]; i += 2) {
int sx = *pp_scanline_nodes++;
int ex = *pp_scanline_nodes++;
@ -579,22 +582,44 @@ pp_rect_t render_nodes(pp_rect_t *tb) {
}
// update render bounds
rb.x = _pp_min(rb.x, sx);
rb.y = _pp_min(rb.y, y);
minx = _pp_min(_pp_min(sx, ex), minx);
maxx = _pp_max(_pp_max(sx, ex), maxx);
rb.h = y - rb.y + 1;
rendered_any = true;
//debug(" - render span at %d from %d to %d\n", y, sx, ex);
if (_pp_antialias) {
int ax = sx >> _pp_antialias;
const int aex = ex >> _pp_antialias;
// rasterise the span into the tile buffer
do {
row_data[sx >> _pp_antialias]++;
} while(++sx < ex);
if (ax == aex) {
row_data[ax] += ex - sx;
continue;
}
row_data[ax] += (1 << _pp_antialias) - (sx & antialias_mask);
for(ax++; ax < aex; ax++) {
row_data[ax] += (1 << _pp_antialias);
}
// This might add 0 to the byte after the end of the row,
// TODO check that's OK
row_data[ax] += ex & antialias_mask;
}
else {
for(int x = sx; x < ex; x++) {
row_data[x]++;
}
}
}
maxx = _pp_max(*(pp_scanline_nodes-1) - 1, maxx);
if (rendered_any) {
maxy = y;
}
else if (y == rb.y) {
++rb.y;
}
}
rb.w = maxx - minx;
rb.w = (maxx >= rb.x) ? maxx + 1 - rb.x : 0;
rb.h = (maxy >= rb.y) ? maxy + 1 - rb.y : 0;
// shifting the width and height effectively "floors" the result which can
// mean we lose a pixel off the right or bottom edge of the tile. by adding