Skip to content

Commit

Permalink
S3 ViRGE: Make IRQs happen in main thread
Browse files Browse the repository at this point in the history
FIFO is also no longer immediately woken up upon writes
  • Loading branch information
Cacodemon345 committed Mar 3, 2025
1 parent 88d9bf6 commit fae2672
Showing 1 changed file with 51 additions and 6 deletions.
57 changes: 51 additions & 6 deletions src/video/vid_s3_virge.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,7 @@ typedef struct virge_t {
event_t * fifo_not_full_event;

atomic_int virge_busy;
atomic_uint virge_irq_req;

uint8_t subsys_stat;
uint8_t subsys_cntl;
Expand Down Expand Up @@ -373,6 +374,9 @@ typedef struct virge_t {
uint32_t dma_mmio_addr;
uint32_t dma_data_type;

pc_timer_t wake_timer;
pc_timer_t irq_timer;

int pci;
int is_agp;
} virge_t;
Expand All @@ -383,6 +387,28 @@ wake_fifo_thread(virge_t *virge) {
thread_set_event(virge->wake_fifo_thread);
}

void
s3_virge_wake_fifo_timer(void* priv)
{
virge_t *virge = (virge_t *) priv;

thread_set_event(virge->wake_fifo_thread); /*Wake up FIFO thread if moving from idle*/
}

void
s3_virge_wake_fifo_thread(virge_t *virge)
{
if (!timer_is_enabled(&virge->wake_timer)) {
/*Don't wake FIFO thread immediately - if we do that it will probably
process one word and go back to sleep, requiring it to be woken on
almost every write. Instead, wait a short while so that the CPU
emulation writes more data so we have more batched-up work.*/
timer_on_auto(&virge->wake_timer, 100.0);
}
if (!timer_is_enabled(&virge->irq_timer))
timer_on_auto(&virge->irq_timer, 100.0);
}

static virge_t *reset_state = NULL;

static video_timings_t timing_diamond_stealth3d_2000_pci = { .type = VIDEO_PCI, .write_b = 2, .write_w = 2, .write_l = 3, .read_b = 28, .read_w = 28, .read_l = 45 };
Expand Down Expand Up @@ -471,6 +497,19 @@ s3_virge_update_irqs(virge_t *virge)
pci_clear_irq(virge->pci_slot, PCI_INTA, &virge->irq_state);
}

void
s3_virge_update_irq_timer(void* priv)
{
virge_t *virge = (virge_t *) priv;

if (virge->virge_irq_req) {
virge->virge_irq_req--;
s3_virge_update_irqs(virge);
}

timer_on_auto(&virge->irq_timer, 100.);
}

static void
s3_virge_out(uint16_t addr, uint8_t val, void *priv)
{
Expand Down Expand Up @@ -1101,6 +1140,9 @@ static void
s3_virge_vblank_start(svga_t *svga) {
virge_t *virge = (virge_t *) svga->priv;

if (virge->virge_irq_req)
virge->virge_irq_req--;

virge->subsys_stat |= INT_VSY;
s3_virge_update_irqs(virge);
}
Expand Down Expand Up @@ -1795,7 +1837,8 @@ fifo_thread(void *param)
if (virge->cmd_dma)
virge->subsys_stat |= (INT_HOST_DONE | INT_CMD_DONE);

s3_virge_update_irqs(virge);
//s3_virge_update_irqs(virge);
virge->virge_irq_req++;
}
}

Expand Down Expand Up @@ -1835,10 +1878,8 @@ s3_virge_queue(virge_t *virge, uint32_t addr, uint32_t val, uint32_t type)

virge->fifo_write_idx++;

if (FIFO_ENTRIES > 0xe000)
wake_fifo_thread(virge);
if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 8)
wake_fifo_thread(virge);
if (FIFO_ENTRIES > 0xe000 || FIFO_ENTRIES < 16)
s3_virge_wake_fifo_thread(virge);
}

static void
Expand Down Expand Up @@ -3642,7 +3683,8 @@ render_thread(void *param)
}
virge->s3d_busy = 0;
virge->subsys_stat |= INT_S3D_DONE;
s3_virge_update_irqs(virge);
//s3_virge_update_irqs(virge);
virge->virge_irq_req++;
}
}

Expand Down Expand Up @@ -4571,6 +4613,9 @@ s3_virge_init(const device_t *info)
virge->fifo_not_full_event = thread_create_event();
virge->fifo_thread = thread_create(fifo_thread, virge);

timer_add(&virge->wake_timer, s3_virge_wake_fifo_timer, virge, 0);
timer_add(&virge->irq_timer, s3_virge_update_irq_timer, virge, 0);

virge->local = info->local;

*reset_state = *virge;
Expand Down

0 comments on commit fae2672

Please sign in to comment.