#include uint8_t AZRP_SHADER_FILLEDCIRCLE = -1; static void azrp_shader_filledcircle_configure(void) { azrp_set_uniforms(AZRP_SHADER_FILLEDCIRCLE, (void *)azrp_width); } __attribute__((constructor)) static void register_shader(void) { extern azrp_shader_t azrp_shader_filledcircle; AZRP_SHADER_FILLEDCIRCLE = azrp_register_shader(azrp_shader_filledcircle, azrp_shader_filledcircle_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 DataFilling[2 * 224]; // Each line of the screen can have a xmin and // a xmax value }; void AddPixelFilledCircle(int16_t xpmin, int16_t xpmax, int16_t yp, struct command *cmd) { if (yp >= 0 && yp < azrp_height) { if (xpmin >= 0) cmd->DataFilling[2 * yp] = xpmin; else cmd->DataFilling[2 * yp] = 0; if (xpmax < azrp_width) cmd->DataFilling[2 * yp + 1] = xpmax; else cmd->DataFilling[2 * yp + 1] = azrp_width - 1; } } void azrp_filledcircle(int xc, int yc, uint16_t rad, uint16_t color) { prof_enter(azrp_perf_cmdgen); int xmin = xc - rad; int xmax = xc + rad; int ymin = yc - rad; int ymax = yc + rad; // The circle is fully outside the screen if ((xmax < 0) || (xmin >= azrp_width) || (ymax < 0) || (ymin >= azrp_height)) { prof_leave(azrp_perf_cmdgen); return; } 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_FILLEDCIRCLE; 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->DataFilling[2 * i] = -1; // reset with value equels -1 cmd->DataFilling[2 * i + 1] = -1; // reset with value equals -1 } int x = 0; int y = rad; int m = 5 - 4 * rad; while (x <= y) { AddPixelFilledCircle(xc - x, xc + x, yc - y, cmd); AddPixelFilledCircle(xc - y, xc + y, yc - x, cmd); AddPixelFilledCircle(xc - x, xc + x, yc + y, cmd); AddPixelFilledCircle(xc - y, xc + y, yc + x, cmd); if (m > 0) { y--; m -= 8 * y; } x++; m += 8 * x + 4; } prof_leave(azrp_perf_cmdgen); } void azrp_shader_filledcircle(void *uniforms, void *comnd, void *fragment) { struct command *cmd = (struct command *)comnd; uint16_t *frag = (uint16_t *)fragment; int16_t *data = (int16_t *)cmd->DataFilling; int BaseAdress = cmd->curr_frag * azrp_frag_height * 2; for (int i = 0; i < azrp_frag_height; i++) { int16_t Xmin = data[BaseAdress + 2 * i]; int16_t Xmax = data[BaseAdress + 2 * i + 1]; if (Xmin != -1 && Xmax != -1) for (int j = Xmin; j <= Xmax; j++) frag[azrp_width * i + j] = cmd->color; } cmd->curr_frag++; }