#include #include 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 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 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) 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) 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 ; ixmin; 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++; }