Merge pull request #4760 from 86Box/tc1995

Some fixes to the Streams engine of the ViRGE/Trio3D
This commit is contained in:
Miran Grča
2024-08-27 22:35:05 +02:00
committed by GitHub

View File

@@ -867,7 +867,7 @@ s3_virge_recalctimings(svga_t *svga)
video_force_resize_set_monitor(1, svga->monitor_index);
}
if (((svga->crtc[0x67] & 0xc) != 0xc) || (virge->chip >= S3_VIRGEGX2)) { /*VGA mode*/
if ((svga->crtc[0x67] & 0xc) != 0xc) { /*VGA mode*/
svga->ma_latch |= (virge->ma_ext << 16);
if (svga->crtc[0x51] & 0x30)
svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
@@ -898,7 +898,7 @@ s3_virge_recalctimings(svga_t *svga)
case 24:
svga->render = svga_render_24bpp_highres;
if ((virge->chip != S3_VIRGEVX) && (virge->chip < S3_VIRGEGX2))
svga->rowoffset = (svga->rowoffset * 3) / 4; /*Hack*/
svga->rowoffset = (svga->rowoffset * 3) >> 2; /*Hack*/
break;
case 32:
svga->render = svga_render_32bpp_highres;
@@ -910,37 +910,32 @@ s3_virge_recalctimings(svga_t *svga)
svga->vram_display_mask = (!(svga->crtc[0x31] & 0x08) &&
(svga->crtc[0x32] & 0x40)) ? 0x3ffff : virge->vram_mask;
svga->overlay.ena = 0;
if (virge->chip >= S3_VIRGEGX2 && (svga->crtc[0x67] & 0xc) == 0xc) {
/* ViRGE/GX2 and later does not use primary stream registers. */
svga->overlay.x = virge->streams.sec_x;
svga->overlay.y = virge->streams.sec_y;
svga->overlay.cur_ysize = virge->streams.sec_h;
if (virge->streams.buffer_ctrl & 2)
svga->overlay.addr = virge->streams.sec_fb1;
else
svga->overlay.addr = virge->streams.sec_fb0;
svga->overlay.ena = (svga->overlay.x >= 0) && !!(virge->streams.blend_ctrl & 0x20);
svga->overlay.v_acc = virge->streams.dda_vert_accumulator;
svga->rowoffset = virge->streams.pri_stride >> 3;
svga->vram_display_mask = virge->vram_mask;
}
} else { /*Streams mode*/
if (virge->streams.buffer_ctrl & 1)
svga->ma_latch = virge->streams.pri_fb1 >> 2;
else
svga->ma_latch = virge->streams.pri_fb0 >> 2;
if (virge->chip < S3_VIRGEGX2) {
if (virge->streams.buffer_ctrl & 1)
svga->ma_latch = virge->streams.pri_fb1 >> 2;
else
svga->ma_latch = virge->streams.pri_fb0 >> 2;
svga->hdisp = virge->streams.pri_w + 1;
if (virge->streams.pri_h < svga->dispend)
svga->dispend = virge->streams.pri_h;
svga->hdisp = virge->streams.pri_w + 1;
if (virge->streams.pri_h < svga->dispend)
svga->dispend = virge->streams.pri_h;
svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x;
svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y;
} else {
svga->ma_latch |= (virge->ma_ext << 16);
if (svga->crtc[0x51] & 0x30)
svga->rowoffset |= (svga->crtc[0x51] & 0x30) << 4;
else if (svga->crtc[0x43] & 0x04)
svga->rowoffset |= 0x100;
if (!svga->rowoffset)
svga->rowoffset = 256;
svga->overlay.x = virge->streams.sec_x;
svga->overlay.y = virge->streams.sec_y;
}
svga->overlay.x = virge->streams.sec_x - virge->streams.pri_x;
svga->overlay.y = virge->streams.sec_y - virge->streams.pri_y;
svga->overlay.cur_ysize = virge->streams.sec_h;
if (virge->streams.buffer_ctrl & 2)
@@ -949,35 +944,60 @@ s3_virge_recalctimings(svga_t *svga)
svga->overlay.addr = virge->streams.sec_fb0;
svga->overlay.ena = (svga->overlay.x >= 0);
svga->overlay.h_acc = virge->streams.dda_horiz_accumulator;
svga->overlay.v_acc = virge->streams.dda_vert_accumulator;
svga->rowoffset = virge->streams.pri_stride >> 3;
if (virge->chip < S3_VIRGEGX2)
svga->rowoffset = virge->streams.pri_stride >> 3;
if (virge->chip <= S3_VIRGEDX && svga->overlay.ena) {
svga->overlay.ena = (((virge->streams.blend_ctrl >> 24) & 7) == 0b000) ||
(((virge->streams.blend_ctrl >> 24) & 7) == 0b101);
} else if (virge->chip == S3_VIRGEGX2 && svga->overlay.ena) {
} else if (virge->chip >= S3_VIRGEGX2 && svga->overlay.ena) {
/* 0x20 = Secondary Stream enabled */
/* 0x2000 = Primary Stream enabled */
svga->overlay.ena = !!(virge->streams.blend_ctrl & 0x20);
}
switch ((virge->streams.pri_ctrl >> 24) & 0x7) {
case 0: /*RGB-8 (CLUT)*/
svga->render = svga_render_8bpp_highres;
break;
case 3: /*KRGB-16 (1.5.5.5)*/
svga->render = svga_render_15bpp_highres;
break;
case 5: /*RGB-16 (5.6.5)*/
svga->render = svga_render_16bpp_highres;
break;
case 6: /*RGB-24 (8.8.8)*/
svga->render = svga_render_24bpp_highres;
break;
case 7: /*XRGB-32 (X.8.8.8)*/
svga->render = svga_render_32bpp_highres;
break;
if (virge->chip >= S3_VIRGEGX2) {
switch (svga->bpp) {
case 8:
svga->render = svga_render_8bpp_highres;
break;
case 15:
svga->render = svga_render_15bpp_highres;
break;
case 16:
svga->render = svga_render_16bpp_highres;
break;
case 24:
svga->render = svga_render_24bpp_highres;
break;
case 32:
svga->render = svga_render_32bpp_highres;
break;
default:
break;
}
} else {
switch ((virge->streams.pri_ctrl >> 24) & 0x7) {
case 0: /*RGB-8 (CLUT)*/
svga->render = svga_render_8bpp_highres;
break;
case 3: /*KRGB-16 (1.5.5.5)*/
svga->render = svga_render_15bpp_highres;
break;
case 5: /*RGB-16 (5.6.5)*/
svga->render = svga_render_16bpp_highres;
break;
case 6: /*RGB-24 (8.8.8)*/
svga->render = svga_render_24bpp_highres;
break;
case 7: /*XRGB-32 (X.8.8.8)*/
svga->render = svga_render_32bpp_highres;
break;
}
}
svga->vram_display_mask = virge->vram_mask;
}
@@ -990,29 +1010,6 @@ s3_virge_recalctimings(svga_t *svga)
svga->render = svga_render_2bpp_s3_highres;
}
static void
s3_virge_update_buffer(virge_t *virge)
{
svga_t *svga = &virge->svga;
if ((svga->crtc[0x67] & 0xc) != 0xc)
return;
if (virge->chip < S3_VIRGEGX2) {
if (virge->streams.buffer_ctrl & 1)
svga->ma_latch = virge->streams.pri_fb1 >> 2;
else
svga->ma_latch = virge->streams.pri_fb0 >> 2;
}
if (virge->streams.buffer_ctrl & 2)
svga->overlay.addr = virge->streams.sec_fb1;
else
svga->overlay.addr = virge->streams.sec_fb0;
svga->rowoffset = virge->streams.pri_stride >> 3;
}
static void
s3_virge_updatemapping(virge_t *virge) {
svga_t *svga = &virge->svga;
@@ -1844,39 +1841,46 @@ s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type)
}
static void
s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv) {
s3_virge_mmio_write(uint32_t addr, uint8_t val, void *priv)
{
virge_t *virge = (virge_t *) priv;
if ((addr & 0xffff) < 0x8000)
s3_virge_queue(virge, addr, val, FIFO_WRITE_BYTE);
else switch (addr & 0xffff) {
case 0x83b0 ... 0x83df:
s3_virge_out(addr & 0x3ff, val, priv);
break;
else {
switch (addr & 0xffff) {
default:
case 0x83b0 ... 0x83df:
s3_virge_out(addr & 0x3ff, val, priv);
break;
case 0xff20:
virge->serialport = val;
i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW));
break;
case 0xff20:
virge->serialport = val;
i2c_gpio_set(virge->i2c, !!(val & SERIAL_PORT_SCW), !!(val & SERIAL_PORT_SDW));
break;
}
}
}
static void
s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv) {
s3_virge_mmio_write_w(uint32_t addr, uint16_t val, void *priv)
{
virge_t *virge = (virge_t *) priv;
if ((addr & 0xfffe) < 0x8000)
s3_virge_queue(virge, addr, val, FIFO_WRITE_WORD);
else switch (addr & 0xfffe) {
default:
case 0x83d4:
s3_virge_mmio_write(addr, val, priv);
s3_virge_mmio_write(addr + 1, val >> 8, priv);
break;
else {
switch (addr & 0xfffe) {
default:
case 0x83d4:
s3_virge_mmio_write(addr, val, priv);
s3_virge_mmio_write(addr + 1, val >> 8, priv);
break;
case 0xff20:
s3_virge_mmio_write(addr, val, priv);
break;
case 0xff20:
s3_virge_mmio_write(addr, val, priv);
break;
}
}
}
@@ -1902,8 +1906,9 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) {
case 0x8190:
virge->streams.sec_ctrl = val;
virge->streams.dda_horiz_accumulator = val & 0xfff;
if (val & (1 << 11))
virge->streams.dda_horiz_accumulator |= 0xfffff800;
if (val & 0x1000)
virge->streams.dda_horiz_accumulator |= ~0xfff;
virge->streams.sdif = (val >> 24) & 7;
break;
case 0x8194:
@@ -1912,50 +1917,56 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) {
case 0x8198:
virge->streams.sec_filter = val;
virge->streams.k1_horiz_scale = val & 0x7ff;
if (val & (1 << 10))
virge->streams.k1_horiz_scale |= 0xfffff800;
if (val & 0x800)
virge->streams.k1_horiz_scale |= ~0x7ff;
virge->streams.k2_horiz_scale = (val >> 16) & 0x7ff;
if ((val >> 16) & (1 << 10))
virge->streams.k2_horiz_scale |= 0xfffff800;
if ((val >> 16) & 0x800)
virge->streams.k2_horiz_scale |= ~0x7ff;
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81a0:
virge->streams.blend_ctrl = val;
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81c0:
virge->streams.pri_fb0 = val & ((virge->memory_size == 8) ?
(val & 0x7fffff) : (val & 0x3fffff));
s3_virge_update_buffer(virge);
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81c4:
virge->streams.pri_fb1 = ((virge->memory_size == 8) ?
(val & 0x7fffff) : (val & 0x3fffff));
s3_virge_update_buffer(virge);
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81c8:
virge->streams.pri_stride = val & 0xfff;
s3_virge_update_buffer(virge);
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81cc:
virge->streams.buffer_ctrl = val;
s3_virge_update_buffer(virge);
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81d0:
virge->streams.sec_fb0 = val;
s3_virge_update_buffer(virge);
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81d4:
virge->streams.sec_fb1 = val;
s3_virge_update_buffer(virge);
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81d8:
virge->streams.sec_stride = val;
s3_virge_update_buffer(virge);
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81dc:
@@ -1963,18 +1974,21 @@ s3_virge_mmio_write_l(uint32_t addr, uint32_t val, void *priv) {
break;
case 0x81e0:
virge->streams.k1_vert_scale = val & 0x7ff;
if (val & (1 << 10))
virge->streams.k1_vert_scale |= 0xfffff800;
if (val & 0x800)
virge->streams.k1_vert_scale |= ~0x7ff;
break;
case 0x81e4:
virge->streams.k2_vert_scale = val & 0x7ff;
if (val & (1 << 10))
virge->streams.k2_vert_scale |= 0xfffff800;
if (val & 0x800)
virge->streams.k2_vert_scale |= ~0x7ff;
break;
case 0x81e8:
virge->streams.dda_vert_accumulator = val & 0xfff;
if (val & (1 << 11))
virge->streams.dda_vert_accumulator |= 0xfffff800;
if (val & 0x1000)
virge->streams.dda_vert_accumulator |= ~0xfff;
svga_recalctimings(svga);
svga->fullchange = changeframecount;
break;
case 0x81ec:
virge->streams.fifo_ctrl = val;
@@ -3968,10 +3982,10 @@ static void s3_virge_hwcursor_draw(svga_t *svga, int displine) {
} while (0)
static void
s3_virge_overlay_draw(svga_t *svga, int displine) {
s3_virge_overlay_draw(svga_t *svga, int displine)
{
virge_t *virge = (virge_t *) svga->priv;
int offset = (virge->streams.sec_x - virge->streams.pri_x) + 1;
int h_acc = virge->streams.dda_horiz_accumulator;
int offset;
int r[8];
int g[8];
int b[8];
@@ -3982,11 +3996,19 @@ s3_virge_overlay_draw(svga_t *svga, int displine) {
uint32_t *p;
uint8_t *src = &svga->vram[svga->overlay_latch.addr];
if (virge->chip < S3_VIRGEGX2)
offset = (virge->streams.sec_x - virge->streams.pri_x) + 1;
else
offset = virge->streams.sec_x + 1;
p = &((uint32_t *)buffer32->line[displine])[offset + svga->x_add];
if ((offset + virge->streams.sec_w) > virge->streams.pri_w)
x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1;
else
if (virge->chip < S3_VIRGEGX2) {
if ((offset + virge->streams.sec_w) > virge->streams.pri_w)
x_size = (virge->streams.pri_w - virge->streams.sec_x) + 1;
else
x_size = virge->streams.sec_w + 1;
} else
x_size = virge->streams.sec_w + 1;
OVERLAY_SAMPLE();
@@ -3994,13 +4016,14 @@ s3_virge_overlay_draw(svga_t *svga, int displine) {
for (x = 0; x < x_size; x++) {
*p++ = r[x_read] | (g[x_read] << 8) | (b[x_read] << 16);
h_acc += virge->streams.k1_horiz_scale;
if (h_acc >= 0) {
svga->overlay_latch.h_acc += virge->streams.k1_horiz_scale;
if (svga->overlay_latch.h_acc >= 0) {
if ((x_read ^ (x_read + 1)) & ~3)
OVERLAY_SAMPLE();
x_read = (x_read + 1) & 7;
h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale);
svga->overlay_latch.h_acc += (virge->streams.k2_horiz_scale - virge->streams.k1_horiz_scale);
}
}