171 lines
4.3 KiB
C++
171 lines
4.3 KiB
C++
#include <azur/gint/render.h>
|
|
#include <cstdlib>
|
|
|
|
uint8_t AZRP_SHADER_FILLEDPOLY = -1;
|
|
|
|
static void azrp_shader_filledpoly_configure(void) {
|
|
azrp_set_uniforms(AZRP_SHADER_FILLEDPOLY, (void *)azrp_width);
|
|
}
|
|
|
|
__attribute__((constructor)) static void register_shader(void) {
|
|
extern azrp_shader_t azrp_shader_filledpoly;
|
|
AZRP_SHADER_FILLEDPOLY = azrp_register_shader(azrp_shader_filledpoly, azrp_shader_filledpoly_configure);
|
|
}
|
|
|
|
|
|
|
|
static int min(int x, int y) { return (x < y) ? x : y; }
|
|
static int max(int x, int y) { return (x > y) ? x : y; }
|
|
|
|
//---
|
|
|
|
#define TABLE_WIDTH
|
|
|
|
struct command {
|
|
uint8_t shader_id;
|
|
uint16_t color;
|
|
uint8_t curr_frag;
|
|
int16_t xmin[224];
|
|
int16_t xmax[224];
|
|
uint8_t empty[224];
|
|
};
|
|
|
|
|
|
void AddPixelFilledPoly(int16_t xpmin, int16_t xpmax, int16_t yp,
|
|
struct command *cmd) {
|
|
if (yp >= 0 && yp < azrp_height) {
|
|
if (xpmin >= 0)
|
|
cmd->xmin[yp] = xpmin;
|
|
else
|
|
cmd->xmin[yp] = 0;
|
|
|
|
if (xpmax < azrp_width)
|
|
cmd->xmax[yp] = xpmax;
|
|
else
|
|
cmd->xmax[yp] = azrp_width - 1;
|
|
}
|
|
}
|
|
|
|
|
|
void azrp_filledpoly(int *x, int *y, int nb_vertices, uint16_t color) {
|
|
prof_enter(azrp_perf_cmdgen);
|
|
|
|
int i, ymin, ymax, xmin2, xmax2, *xmin, *xmax;
|
|
char *empty;
|
|
|
|
if(nb_vertices < 3) {
|
|
prof_leave(azrp_perf_cmdgen);
|
|
return;
|
|
}
|
|
|
|
ymin = ymax = y[0];
|
|
xmin2 = xmax2 = x[0];
|
|
|
|
for(i=0 ; i<nb_vertices ; i++) {
|
|
if(y[i] < ymin) ymin = y[i];
|
|
if(y[i] > ymax) ymax = y[i];
|
|
if(x[i] < xmin2) xmin2 = x[i];
|
|
if(x[i] > xmax2) xmax2 = x[i];
|
|
}
|
|
|
|
// The polygon is fully outside the screen
|
|
if ((xmax2 < 0) || (xmin2 >= azrp_width) || (ymax < 0) ||
|
|
(ymin >= azrp_height)) {
|
|
prof_leave(azrp_perf_cmdgen);
|
|
return;
|
|
}
|
|
|
|
xmin = (int*) malloc((ymax-ymin+1)*sizeof(int));
|
|
xmax = (int*) malloc((ymax-ymin+1)*sizeof(int));
|
|
empty = (char*) malloc(ymax-ymin+1);
|
|
|
|
|
|
int ytop = max(ymin, 0);
|
|
int ybot = min(ymax, azrp_height - 1);
|
|
|
|
int frag_first = ytop / azrp_frag_height;
|
|
int frag_last = ybot / azrp_frag_height;
|
|
int frag_count = frag_last - frag_first + 1;
|
|
|
|
struct command *cmd = (struct command *) azrp_new_command(sizeof *cmd, frag_first, frag_count);
|
|
if(!cmd) {
|
|
prof_leave(azrp_perf_cmdgen);
|
|
return;
|
|
}
|
|
|
|
cmd->shader_id = AZRP_SHADER_FILLEDPOLY;
|
|
cmd->color = color;
|
|
cmd->curr_frag = frag_first;
|
|
|
|
// reset the point counters in each cell of the table
|
|
for (int i = 0; i < 224; i++) {
|
|
cmd->xmin[i] = -1; // reset with value equels -1
|
|
cmd->xmax[i] = -1; // reset with value equals -1
|
|
}
|
|
|
|
if(xmin && xmax && empty) {
|
|
for(i=0 ; i<ymax-ymin+1 ; i++) empty[i] = 1;
|
|
for(i=0 ; i<nb_vertices ; i++) {
|
|
int j, px, py, dx, dy, sx, sy, cumul;
|
|
px = x[i];
|
|
py = y[i];
|
|
dx = x[(i+1)%nb_vertices]-px;
|
|
dy = y[(i+1)%nb_vertices]-py;
|
|
sx = (dx > 0) ? 1 : -1;
|
|
sy = (dy > 0) ? 1 : -1;
|
|
dx = (dx > 0) ? dx : -dx;
|
|
dy = (dy > 0) ? dy : -dy;
|
|
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
|
|
if(dx > dy) {
|
|
cumul = dx >> 1;
|
|
for(j=1 ; j<dx ; j++) {
|
|
px += sx;
|
|
cumul += dy;
|
|
if(cumul > dx) cumul -= dx, py += sy;
|
|
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
|
|
}
|
|
} else {
|
|
cumul = dy >> 1;
|
|
for(j=1 ; j<dy ; j++) {
|
|
py += sy;
|
|
cumul += dx;
|
|
if(cumul > dy) cumul -= dy, px += sx;
|
|
if(empty[py-ymin]) xmax[py-ymin]=xmin[py-ymin]=px, empty[py-ymin]=0; else xmax[py-ymin]=px;
|
|
}
|
|
}
|
|
}
|
|
for(i=0 ; i<ymax-ymin+1 ; i++)
|
|
AddPixelFilledPoly(xmin[i], xmax[i], ymin+i, cmd);
|
|
}
|
|
free(xmin);
|
|
free(xmax);
|
|
free(empty);
|
|
|
|
prof_leave(azrp_perf_cmdgen);
|
|
}
|
|
|
|
void azrp_shader_filledpoly(void *uniforms, void *comnd, void *fragment) {
|
|
struct command *cmd = (struct command *)comnd;
|
|
uint16_t *frag = (uint16_t *)fragment;
|
|
|
|
int16_t *Xmindata = (int16_t *)cmd->xmin;
|
|
int16_t *Xmaxdata = (int16_t *)cmd->xmax;
|
|
|
|
int BaseAdress = cmd->curr_frag * azrp_frag_height;
|
|
|
|
for (int i = 0; i < azrp_frag_height; i++)
|
|
{
|
|
int16_t Xmin = Xmindata[BaseAdress + i];
|
|
int16_t Xmax = Xmaxdata[BaseAdress + i];
|
|
|
|
if (Xmin != -1 && Xmax != -1)
|
|
{
|
|
if (Xmin<=Xmax)
|
|
for (int j = Xmin; j <= Xmax; j++) frag[azrp_width * i + j] = cmd->color;
|
|
else
|
|
for (int j = Xmax; j <= Xmin; j++) frag[azrp_width * i + j] = cmd->color;
|
|
}
|
|
}
|
|
|
|
cmd->curr_frag++;
|
|
} |