Azur/azur/src/gint/shaders/line.c

168 lines
3.6 KiB
C

#include <azur/gint/render.h>
uint8_t AZRP_SHADER_LINE = -1;
__attribute__((constructor))
static void register_shader(void)
{
extern azrp_shader_t azrp_shader_line;
AZRP_SHADER_LINE = azrp_register_shader(azrp_shader_line);
}
void azrp_shader_line_configure(void)
{
azrp_set_uniforms(AZRP_SHADER_LINE, (void *)azrp_width);
}
static int min(int x, int y)
{
return (x < y) ? x : y;
}
static int max(int x, int y)
{
return (x > y) ? x : y;
}
//---
struct command {
uint8_t shader_id;
uint16_t color;
uint16_t curr_y;
uint16_t curr_x;
int16_t dx, dy, sx, sy;
int16_t cumul;
int16_t i;
};
int ABS( int x1 )
{
if (x1 >= 0) return x1;
else return (-1 * x1);
}
int SGN( int x1 )
{
if (x1 > 0) return 1;
else if (x1 == 0) return 0;
else return -1;
}
void azrp_line(int xA, int yA, int xB, int yB, int color)
{
prof_enter(azrp_perf_cmdgen);
int x1, x2;
int y1, y2;
// we swap to always start with the point on top as the fragment are updated from top to bottom
if (yA <= yB)
{
x1 = xA;
y1 = yA;
x2 = xB;
y2 = yB;
}
else
{
x1 = xB;
y1 = yB;
x2 = xA;
y2 = yA;
}
int frag_first = y1 >> 4;
int frag_last = y2 >> 4;
int frag_count = frag_last - frag_first + 1;
struct command cmd;
cmd.shader_id = AZRP_SHADER_LINE;
cmd.color = color;
cmd.curr_x = x1;
cmd.curr_y = y1 & 15;
cmd.dx = ABS(x2-x1);
cmd.sx = SGN(x2-x1);
cmd.dy = ABS(y2-y1);
cmd.sy = SGN(y2-y1);
cmd.i = 0;
cmd.cumul = (cmd.dx >= cmd.dy) ? cmd.dx >> 1 : cmd.dy >> 1;
azrp_queue_command(&cmd, sizeof cmd, frag_first, frag_count);
prof_leave(azrp_perf_cmdgen);
}
void azrp_shader_line( void *uniforms, void *comnd, void *fragment )
{
struct command *cmd = (struct command *) comnd;
uint16_t *frag = (uint16_t *) fragment;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
int i;
if (cmd->dy == 0)
{
for( i = cmd->i; i < cmd->dx ; i++ )
{
cmd->curr_x += cmd->sx;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
else if (cmd->dx == 0)
{
for( i = cmd->i; i < cmd->dy ; i++ )
{
cmd->curr_y += cmd->sy;
// if curr_y=16, this means we are changing to next fragment
if (cmd->curr_y == azrp_frag_height) break;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
else if (cmd->dx >= cmd->dy)
{
for( i = cmd->i; i < cmd->dx; i++ )
{
cmd->curr_x += cmd->sx;
cmd->cumul += cmd->dy;
if (cmd->cumul > cmd->dx)
{
cmd->cumul -= cmd->dx;
cmd->curr_y += cmd->sy;
}
// if curr_y=16, this means we are changing to next fragment
if (cmd->curr_y == azrp_frag_height ) break;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
else
{
for( i = cmd->i; i < cmd->dy; i++ )
{
cmd->curr_y += cmd->sy;
cmd->cumul += cmd->dx;
if (cmd->cumul > cmd->dy)
{
cmd->cumul -= cmd->dy;
cmd->curr_x += cmd->sx;
}
// if curr_y=16, this means we are changing to next fragment
if (cmd->curr_y == azrp_frag_height) break;
frag[ azrp_width * cmd->curr_y + cmd->curr_x ] = cmd->color;
}
}
cmd->curr_y = cmd->curr_y & 15;
cmd->i = i+1;
}