Implemented ViRGE 2D Polygon Fill command.

Improvements to ViRGE line draw.
This commit is contained in:
TomW 2015-09-26 17:56:55 +01:00
commit 3e314ccdfb

View file

@ -143,6 +143,14 @@ typedef struct virge_t
uint32_t pattern_8[8*8];
uint32_t pattern_16[8*8];
uint32_t pattern_32[8*8];
uint32_t prdx;
uint32_t prxstart;
uint32_t pldx;
uint32_t plxstart;
uint32_t pystart;
uint32_t pycnt;
uint32_t dest_l, dest_r;
} s3d;
s3d_t s3d_tri;
@ -237,6 +245,7 @@ enum
CMD_SET_COMMAND_BITBLT = (0 << 27),
CMD_SET_COMMAND_RECTFILL = (2 << 27),
CMD_SET_COMMAND_LINE = (3 << 27),
CMD_SET_COMMAND_POLY = (5 << 27),
CMD_SET_COMMAND_NOP = (15 << 27)
};
@ -790,10 +799,10 @@ static uint32_t s3_virge_mmio_read_l(uint32_t addr, void *p)
case 0xa4e4:
ret = (virge->s3d.dest_str << 16) | virge->s3d.src_str;
break;
case 0xa4e8:
case 0xa4e8: case 0xace8:
ret = virge->s3d.mono_pat_0;
break;
case 0xa4ec:
case 0xa4ec: case 0xacec:
ret = virge->s3d.mono_pat_1;
break;
case 0xa4f0:
@ -1080,16 +1089,16 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
virge->s3d.dest_str = (val >> 16) & 0xff8;
virge->s3d.src_str = val & 0xff8;
break;
case 0xa4e8:
case 0xa4e8: case 0xace8:
virge->s3d.mono_pat_0 = val;
break;
case 0xa4ec:
case 0xa4ec: case 0xacec:
virge->s3d.mono_pat_1 = val;
break;
case 0xa4f0:
case 0xa4f0: case 0xacf0:
virge->s3d.pat_bg_clr = val;
break;
case 0xa4f4: case 0xa8f4:
case 0xa4f4: case 0xa8f4: case 0xacf4:
virge->s3d.pat_fg_clr = val;
break;
case 0xa4f8:
@ -1136,6 +1145,32 @@ static void s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *p)
if (virge->s3d.cmd_set & CMD_SET_AE)
s3_virge_bitblt(virge, -1, 0);
break;
case 0xad00:
virge->s3d.cmd_set = val;
if (!(val & CMD_SET_AE))
s3_virge_bitblt(virge, -1, 0);
break;
case 0xad68:
virge->s3d.prdx = val;
break;
case 0xad6c:
virge->s3d.prxstart = val;
break;
case 0xad70:
virge->s3d.pldx = val;
break;
case 0xad74:
virge->s3d.plxstart = val;
break;
case 0xad78:
virge->s3d.pystart = val & 0x7ff;
break;
case 0xad7c:
virge->s3d.pycnt = val & 0x300007ff;
if (virge->s3d.cmd_set & CMD_SET_AE)
s3_virge_bitblt(virge, -1, 0);
break;
case 0xb4d4:
virge->s3d_tri.z_base = val & 0x3ffff8;
@ -1651,17 +1686,30 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat)
virge->s3d.dest_y = virge->s3d.lystart;
virge->s3d.h = virge->s3d.lycnt;
virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff;
if (virge->s3d.ldx >= 0)
virge->s3d.dest_x -= virge->s3d.ldx / 2;
else
virge->s3d.dest_x += virge->s3d.ldx / 2;
//virge->s3d.dest_dest_x = virge->s3d.dest_x + virge->s3d.ldx;
}
while (virge->s3d.h)
{
int x = virge->s3d.dest_x >> 20;
int new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20;
int x;
int new_x;
int first_pixel = 1;
x = virge->s3d.dest_x >> 20;
if (virge->s3d.h == virge->s3d.lycnt &&
((virge->s3d.line_dir && x > virge->s3d.lxend0) ||
(!virge->s3d.line_dir && x < virge->s3d.lxend0)))
x = virge->s3d.lxend0;
if (virge->s3d.h == 1)
new_x = virge->s3d.lxend1 + (virge->s3d.line_dir ? 1 : -1);
else
new_x = (virge->s3d.dest_x + virge->s3d.ldx) >> 20;
if ((virge->s3d.line_dir && x > new_x) ||
(!virge->s3d.line_dir && x < new_x))
goto skip_line;
do
{
uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (virge->s3d.dest_y * virge->s3d.dest_str);
@ -1669,6 +1717,16 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat)
uint32_t out = 0;
int update = 1;
if ((virge->s3d.h == virge->s3d.lycnt || !first_pixel) &&
((virge->s3d.line_dir && x < virge->s3d.lxend0) ||
(!virge->s3d.line_dir && x > virge->s3d.lxend0)))
update = 0;
if ((virge->s3d.h == 1 || !first_pixel) &&
((virge->s3d.line_dir && x > virge->s3d.lxend1) ||
(!virge->s3d.line_dir && x < virge->s3d.lxend1)))
update = 0;
CLIP(x, virge->s3d.dest_y);
if (update)
@ -1685,14 +1743,61 @@ static void s3_virge_bitblt(virge_t *virge, int count, uint32_t cpu_dat)
x++;
else if (x > new_x)
x--;
first_pixel = 0;
} while (x != new_x);
skip_line:
virge->s3d.dest_x += virge->s3d.ldx;
virge->s3d.dest_y--;
virge->s3d.h--;
}
break;
case CMD_SET_COMMAND_POLY:
/*No source*/
if (virge->s3d.pycnt & (1 << 28))
virge->s3d.dest_r = virge->s3d.prxstart;
if (virge->s3d.pycnt & (1 << 29))
virge->s3d.dest_l = virge->s3d.plxstart;
virge->s3d.h = virge->s3d.pycnt & 0x7ff;
virge->s3d.rop = (virge->s3d.cmd_set >> 17) & 0xff;
//pclog("Start poly - l=%08x r=%08x h=%i rop=%02x\n", virge->s3d.dest_l, virge->s3d.dest_r, virge->s3d.h, virge->s3d.rop);
while (virge->s3d.h)
{
int x = virge->s3d.dest_l >> 20;
int xend = virge->s3d.dest_r >> 20;
int y = virge->s3d.pystart & 0x7ff;
int xdir = (x < xend) ? 1 : -1;
//pclog(" %03i: %i - %i %08x-%08x\n", y, x, xend, virge->s3d.dest_l, virge->s3d.dest_r);
do
{
uint32_t dest_addr = virge->s3d.dest_base + (x * x_mul) + (y * virge->s3d.dest_str);
uint32_t source = 0, dest, pattern;
uint32_t out = 0;
int update = 1;
CLIP(x, y);
if (update)
{
READ(dest_addr, dest);
pattern = pattern_data[(y & 7)*8 + (x & 7)];
MIX();
WRITE(dest_addr, out);
}
x = (x + xdir) & 0x7ff;
}
while (x != (xend + xdir));
virge->s3d.dest_l += virge->s3d.pldx;
virge->s3d.dest_r += virge->s3d.prdx;
virge->s3d.h--;
virge->s3d.pystart = (virge->s3d.pystart - 1) & 0x7ff;
}
break;
default:
fatal("s3_virge_bitblt : blit command %i %08x\n", (virge->s3d.cmd_set >> 27) & 0xf, virge->s3d.cmd_set);
}