#include uint8_t AZRP_SHADER_CIRCLE = -1; static void azrp_shader_circle_configure(void) { azrp_set_uniforms(AZRP_SHADER_CIRCLE, (void *)azrp_width); } __attribute__((constructor)) static void register_shader(void) { extern azrp_shader_t azrp_shader_circle; AZRP_SHADER_CIRCLE = azrp_register_shader(azrp_shader_circle, azrp_shader_circle_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 256 struct command { uint8_t shader_id; uint16_t color; uint8_t curr_frag; uint16_t NbPixels[14]; // Nunmber of pixels in each fragment uint16_t DataPixelsX[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width uint16_t DataPixelsY[14*TABLE_WIDTH]; // 14 fragments each able to store as much pixels as width }; void AddPixelCircle( int16_t xp, int16_t yp, struct command *cmd ) { if (xp >= 0 && xp < azrp_width && yp >= 0 && yp < azrp_height) { uint8_t cfrag = yp / azrp_frag_height; uint16_t nbpixinfrag = cmd->NbPixels[ cfrag ]; uint16_t index = cfrag * TABLE_WIDTH + nbpixinfrag; cmd->DataPixelsX[ index ] = xp; cmd->DataPixelsY[ index ] = yp & 15; cmd->NbPixels[ cfrag ]++; } } void azrp_circle(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_CIRCLE; cmd->color = color; cmd->curr_frag = frag_first; // reset the point counters in each cell of the table for( int i = 0; i < 14; i++ ) cmd->NbPixels[i]=0; int x = 0; int y = rad; int m = 5 - 4*rad; while (x <= y) { AddPixelCircle( xc+x, yc+y, cmd ); AddPixelCircle( xc+y, yc+x, cmd ); AddPixelCircle( xc-x, yc+y, cmd ); AddPixelCircle( xc-y, yc+x, cmd ); AddPixelCircle( xc+x, yc-y, cmd ); AddPixelCircle( xc+y, yc-x, cmd ); AddPixelCircle( xc-x, yc-y, cmd ); AddPixelCircle( 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_circle( void *uniforms, void *comnd, void *fragment ) { struct command *cmd = (struct command *) comnd; uint16_t *frag = (uint16_t *) fragment; uint16_t *taille = (uint16_t *) cmd->NbPixels; uint16_t *DX = (uint16_t *) cmd->DataPixelsX; uint16_t *DY = (uint16_t *) cmd->DataPixelsY; uint16_t nbpix = taille[ cmd->curr_frag ]; int BaseAdress = cmd->curr_frag * TABLE_WIDTH; for( int i = 0; i < nbpix; i++ ) { uint16_t X = DX[ BaseAdress + i ]; uint16_t Y = DY[ BaseAdress + i ]; frag[ azrp_width * Y + X ] = cmd->color; } cmd->curr_frag++; }