Implemented combined PCI / memory FIFO. This is required for running Voodoo1
games / demos correctly on the Voodoo2 model. I noticed a small slowdown (2 or 3 percent) on the Voodoo1.
This commit is contained in:
parent
c1d5947a80
commit
da48346f9d
@ -158,12 +158,22 @@ void CDECL libvoodoo_LTX_plugin_fini(void)
|
||||
BX_THREAD_FUNC(fifo_thread, indata)
|
||||
{
|
||||
Bit32u type, offset = 0, data = 0, regnum;
|
||||
fifo_state *fifo;
|
||||
|
||||
UNUSED(indata);
|
||||
while (1) {
|
||||
if (fifo_wait_for_event(&fifo_wakeup)) {
|
||||
while (!fifo_empty(&v->fbi.fifo)) {
|
||||
type = fifo_remove(&v->fbi.fifo, &offset, &data);
|
||||
BX_LOCK(fifo_mutex);
|
||||
while (1) {
|
||||
if (!fifo_empty(&v->fbi.fifo)) {
|
||||
fifo = &v->fbi.fifo;
|
||||
} else if (!fifo_empty(&v->pci.fifo)) {
|
||||
fifo = &v->pci.fifo;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
type = fifo_remove(fifo, &offset, &data);
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
switch (type) {
|
||||
case FIFO_WR_REG:
|
||||
if ((offset & 0x800c0) == 0x80000 && v->alt_regmap)
|
||||
@ -191,7 +201,10 @@ BX_THREAD_FUNC(fifo_thread, indata)
|
||||
lfb_w(offset, data, 0xffff0000);
|
||||
break;
|
||||
}
|
||||
BX_LOCK(fifo_mutex);
|
||||
}
|
||||
v->pci.op_pending = 0;
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
if (v->fbi.cmdfifo[0].enabled) {
|
||||
while (v->fbi.cmdfifo[0].enabled && (v->fbi.cmdfifo[0].depth >= v->fbi.cmdfifo[0].depth_needed)) {
|
||||
cmdfifo_process();
|
||||
@ -645,9 +658,11 @@ void bx_voodoo_c::vertical_timer_handler(void *this_ptr)
|
||||
|
||||
BX_VOODOO_THIS s.vdraw.frame_start = bx_virt_timer.time_usec(0);
|
||||
|
||||
if (!fifo_empty(&v->fbi.fifo)) {
|
||||
BX_LOCK(fifo_mutex);
|
||||
if (!fifo_empty(&v->pci.fifo) || !fifo_empty(&v->fbi.fifo)) {
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
}
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
if (v->fbi.cmdfifo[0].cmd_ready) {
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
}
|
||||
|
@ -1461,7 +1461,7 @@ struct _pci_state
|
||||
fifo_state fifo; /* PCI FIFO */
|
||||
Bit32u init_enable; /* initEnable value */
|
||||
Bit8u stall_state; /* state of the system if we're stalled */
|
||||
Bit8u op_pending; /* true if an operation is pending */
|
||||
Bit16u op_pending; /* number of operations pending */
|
||||
Bit32u fifo_mem[64*2]; /* memory backing the PCI FIFO */
|
||||
};
|
||||
|
||||
@ -1792,8 +1792,7 @@ BX_CPP_INLINE void fifo_reset(fifo_state *f)
|
||||
|
||||
BX_CPP_INLINE bx_bool fifo_full(fifo_state *f)
|
||||
{
|
||||
bx_bool ret = (f->in + 2 == f->out || (f->in == f->size - 2 && f->out == 0));
|
||||
return ret;
|
||||
return (f->in + 2 == f->out || (f->in == f->size - 2 && f->out == 0));
|
||||
}
|
||||
|
||||
|
||||
@ -1820,7 +1819,6 @@ BX_CPP_INLINE void fifo_add(fifo_state *f, Bit32u offset, Bit32u data)
|
||||
{
|
||||
Bit32s next_in;
|
||||
|
||||
BX_LOCK(fifo_mutex);
|
||||
if (fifo_full(f)) {
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
@ -1839,10 +1837,6 @@ BX_CPP_INLINE void fifo_add(fifo_state *f, Bit32u offset, Bit32u data)
|
||||
f->base[f->in + 1] = data;
|
||||
f->in = next_in;
|
||||
}
|
||||
if (fifo_space(f) <= 16) {
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
}
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
}
|
||||
|
||||
|
||||
@ -1850,7 +1844,6 @@ BX_CPP_INLINE Bit32u fifo_remove(fifo_state *f, Bit32u *offset, Bit32u *data)
|
||||
{
|
||||
Bit32u type = 0;
|
||||
|
||||
BX_LOCK(fifo_mutex);
|
||||
/* as long as we have data, we can do it */
|
||||
if (f->out != f->in)
|
||||
{
|
||||
@ -1871,12 +1864,17 @@ BX_CPP_INLINE Bit32u fifo_remove(fifo_state *f, Bit32u *offset, Bit32u *data)
|
||||
if (fifo_space(f) > 15) {
|
||||
fifo_set_event(&fifo_not_full);
|
||||
}
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
return type;
|
||||
}
|
||||
|
||||
|
||||
BX_CPP_INLINE bx_bool fifo_empty(fifo_state *f)
|
||||
{
|
||||
return (f->in == f->out);
|
||||
}
|
||||
|
||||
|
||||
BX_CPP_INLINE bx_bool fifo_empty_locked(fifo_state *f)
|
||||
{
|
||||
BX_LOCK(fifo_mutex);
|
||||
bx_bool ret = (f->in == f->out);
|
||||
@ -1885,6 +1883,26 @@ BX_CPP_INLINE bx_bool fifo_empty(fifo_state *f)
|
||||
}
|
||||
|
||||
|
||||
BX_CPP_INLINE void fifo_move(fifo_state *f1, fifo_state *f2)
|
||||
{
|
||||
if (fifo_full(f2)) {
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
fifo_wait_for_event(&fifo_not_full);
|
||||
BX_LOCK(fifo_mutex);
|
||||
}
|
||||
Bit32s items1 = fifo_items(f1);
|
||||
Bit32s space2 = fifo_space(f2);
|
||||
while ((items1 > 0) && (space2 > 0)) {
|
||||
f2->base[f2->in++] = f1->base[f1->out++];
|
||||
if (f2->in >= f2->size) f2->in = 0;
|
||||
if (f1->out >= f1->size) f1->out = 0;
|
||||
items1--;
|
||||
space2--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifndef PTR64
|
||||
#define count_leading_zeros _count_leading_zeros
|
||||
BX_CPP_INLINE Bit8u _count_leading_zeros(Bit32u value)
|
||||
|
@ -1307,7 +1307,7 @@ void recompute_video_memory(voodoo_state *v)
|
||||
|
||||
/* reset the FIFO */
|
||||
fifo_reset(&v->fbi.fifo);
|
||||
if (fifo_empty(&v->pci.fifo)) v->pci.op_pending = 0;
|
||||
if (fifo_empty_locked(&v->pci.fifo)) v->pci.op_pending = 0;
|
||||
|
||||
/* reset our front/back buffers if they are out of range */
|
||||
if (v->fbi.rgboffs[2] == (Bit32u)~0)
|
||||
@ -2680,6 +2680,32 @@ void cmdfifo_process(void)
|
||||
}
|
||||
|
||||
|
||||
bx_bool fifo_add_common(Bit32u type_offset, Bit32u data)
|
||||
{
|
||||
bx_bool ret = 0;
|
||||
|
||||
BX_LOCK(fifo_mutex);
|
||||
if (v->pci.fifo.enabled) {
|
||||
fifo_add(&v->pci.fifo, type_offset, data);
|
||||
ret = 1;
|
||||
if (v->fbi.fifo.enabled) {
|
||||
if ((fifo_space(&v->pci.fifo)/2) <= 16) {
|
||||
fifo_move(&v->pci.fifo, &v->fbi.fifo);
|
||||
}
|
||||
if ((fifo_space(&v->fbi.fifo)/2) <= 0xe000) {
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
}
|
||||
} else {
|
||||
if ((fifo_space(&v->pci.fifo)/2) <= 16) {
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
}
|
||||
}
|
||||
}
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void register_w_common(Bit32u offset, Bit32u data)
|
||||
{
|
||||
Bit32u regnum = (offset) & 0xff;
|
||||
@ -2881,18 +2907,17 @@ void register_w_common(Bit32u offset, Bit32u data)
|
||||
break;
|
||||
|
||||
default:
|
||||
if (v->fbi.fifo.enabled) {
|
||||
fifo_add(&v->fbi.fifo, FIFO_WR_REG | offset, data);
|
||||
if (fifo_add_common(FIFO_WR_REG | offset, data)) {
|
||||
BX_LOCK(fifo_mutex);
|
||||
if ((regnum == triangleCMD) || (regnum == ftriangleCMD) || (regnum == nopCMD) ||
|
||||
(regnum == fastfillCMD) || (regnum == swapbufferCMD)) {
|
||||
BX_LOCK(fifo_mutex);
|
||||
v->pci.op_pending++;
|
||||
if (regnum == swapbufferCMD) {
|
||||
v->fbi.swaps_pending++;
|
||||
}
|
||||
fifo_set_event(&fifo_wakeup);
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
}
|
||||
BX_UNLOCK(fifo_mutex);
|
||||
} else {
|
||||
register_w(offset, data, 0);
|
||||
}
|
||||
@ -2932,7 +2957,7 @@ Bit32u register_r(Bit32u offset)
|
||||
result = 0;
|
||||
|
||||
/* bits 5:0 are the PCI FIFO free space */
|
||||
if (fifo_empty(&v->pci.fifo))
|
||||
if (fifo_empty_locked(&v->pci.fifo))
|
||||
result |= 0x3f << 0;
|
||||
else
|
||||
{
|
||||
@ -2970,7 +2995,7 @@ Bit32u register_r(Bit32u offset)
|
||||
result |= v->fbi.frontbuf << 10;
|
||||
|
||||
/* bits 27:12 indicate memory FIFO freespace */
|
||||
if (!v->fbi.fifo.enabled || fifo_empty(&v->fbi.fifo))
|
||||
if (!v->fbi.fifo.enabled || fifo_empty_locked(&v->fbi.fifo))
|
||||
result |= 0xffff << 12;
|
||||
else
|
||||
{
|
||||
@ -3116,24 +3141,23 @@ Bit32u lfb_r(Bit32u offset)
|
||||
|
||||
void voodoo_w(Bit32u offset, Bit32u data, Bit32u mask)
|
||||
{
|
||||
Bit32u type;
|
||||
|
||||
if ((offset & (0xc00000/4)) == 0)
|
||||
register_w_common(offset, data);
|
||||
else if (offset & (0x800000/4)) {
|
||||
if (v->fbi.fifo.enabled) {
|
||||
fifo_add(&v->fbi.fifo, FIFO_WR_TEX | offset, data);
|
||||
} else {
|
||||
if (!fifo_add_common(FIFO_WR_TEX | offset, data)) {
|
||||
texture_w(offset, data);
|
||||
}
|
||||
} else {
|
||||
if (v->fbi.fifo.enabled) {
|
||||
if (mask == 0xffffffff) {
|
||||
fifo_add(&v->fbi.fifo, FIFO_WR_FBI_32 | offset, data);
|
||||
} else if (mask & 1) {
|
||||
fifo_add(&v->fbi.fifo, FIFO_WR_FBI_16L | offset, data);
|
||||
} else {
|
||||
fifo_add(&v->fbi.fifo, FIFO_WR_FBI_16H | offset, data);
|
||||
}
|
||||
if (mask == 0xffffffff) {
|
||||
type = FIFO_WR_FBI_32;
|
||||
} else if (mask & 1) {
|
||||
type = FIFO_WR_FBI_16L;
|
||||
} else {
|
||||
type = FIFO_WR_FBI_16H;
|
||||
}
|
||||
if (!fifo_add_common(type | offset, data)) {
|
||||
lfb_w(offset, data, mask);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user