Skip to content

Commit

Permalink
nv2a: Block renderer finalization on display present
Browse files Browse the repository at this point in the history
  • Loading branch information
mborgerson committed Jul 23, 2024
1 parent 2a13bf7 commit da59a60
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 12 deletions.
1 change: 1 addition & 0 deletions hw/xbox/nv2a/nv2a.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
void nv2a_init(PCIBus *bus, int devfn, MemoryRegion *ram);
void nv2a_context_init(void);
int nv2a_get_framebuffer_surface(void);
void nv2a_release_framebuffer_surface(void);
void nv2a_set_surface_scale_factor(unsigned int scale);
unsigned int nv2a_get_surface_scale_factor(void);
const uint8_t *nv2a_get_dac_palette(void);
Expand Down
4 changes: 0 additions & 4 deletions hw/xbox/nv2a/pgraph/gl/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ void pgraph_gl_set_surface_scale_factor(NV2AState *d, unsigned int scale)

g_config.display.quality.surface_scale = scale < 1 ? 1 : scale;

qemu_mutex_unlock_iothread();

qemu_mutex_lock(&d->pfifo.lock);
qatomic_set(&d->pfifo.halt, true);
qemu_mutex_unlock(&d->pfifo.lock);
Expand All @@ -67,8 +65,6 @@ void pgraph_gl_set_surface_scale_factor(NV2AState *d, unsigned int scale)
qatomic_set(&d->pfifo.halt, false);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);

qemu_mutex_lock_iothread();
}

unsigned int pgraph_gl_get_surface_scale_factor(NV2AState *d)
Expand Down
29 changes: 25 additions & 4 deletions hw/xbox/nv2a/pgraph/pgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ void pgraph_init(NV2AState *d)
qemu_mutex_init(&pg->renderer_lock);
qemu_event_init(&pg->sync_complete, false);
qemu_event_init(&pg->flush_complete, false);
qemu_cond_init(&pg->framebuffer_released);

pg->frame_time = 0;
pg->draw_time = 0;
Expand Down Expand Up @@ -352,38 +353,55 @@ void pgraph_destroy(PGRAPHState *pg)
int nv2a_get_framebuffer_surface(void)
{
NV2AState *d = g_nv2a;
PGRAPHState *pg = &d->pgraph;
int s = 0;

qemu_mutex_lock(&d->pgraph.renderer_lock);
if (d->pgraph.renderer->ops.get_framebuffer_surface) {
s = d->pgraph.renderer->ops.get_framebuffer_surface(d);
qemu_mutex_lock(&pg->renderer_lock);
assert(!pg->framebuffer_in_use);
pg->framebuffer_in_use = true;
if (pg->renderer->ops.get_framebuffer_surface) {
s = pg->renderer->ops.get_framebuffer_surface(d);
}
qemu_mutex_unlock(&d->pgraph.renderer_lock);
qemu_mutex_unlock(&pg->renderer_lock);

return s;
}

void nv2a_release_framebuffer_surface(void)
{
NV2AState *d = g_nv2a;
PGRAPHState *pg = &d->pgraph;
qemu_mutex_lock(&pg->renderer_lock);
pg->framebuffer_in_use = false;
qemu_cond_broadcast(&pg->framebuffer_released);
qemu_mutex_unlock(&pg->renderer_lock);
}

void nv2a_set_surface_scale_factor(unsigned int scale)
{
NV2AState *d = g_nv2a;

qemu_mutex_unlock_iothread();
qemu_mutex_lock(&d->pgraph.renderer_lock);
if (d->pgraph.renderer->ops.set_surface_scale_factor) {
d->pgraph.renderer->ops.set_surface_scale_factor(d, scale);
}
qemu_mutex_unlock(&d->pgraph.renderer_lock);
qemu_mutex_lock_iothread();
}

unsigned int nv2a_get_surface_scale_factor(void)
{
NV2AState *d = g_nv2a;
int s = 1;

qemu_mutex_unlock_iothread();
qemu_mutex_lock(&d->pgraph.renderer_lock);
if (d->pgraph.renderer->ops.get_surface_scale_factor) {
s = d->pgraph.renderer->ops.get_surface_scale_factor(d);
}
qemu_mutex_unlock(&d->pgraph.renderer_lock);
qemu_mutex_lock_iothread();

return s;
}
Expand Down Expand Up @@ -2958,6 +2976,9 @@ void pgraph_process_pending(NV2AState *d)

qemu_mutex_unlock(&d->pfifo.lock);
qemu_mutex_lock(&d->pgraph.lock);
while (pg->framebuffer_in_use) {
qemu_cond_wait(&d->pgraph.framebuffer_released, &d->pgraph.renderer_lock);
}

if (pg->renderer->ops.finalize) {
pg->renderer->ops.finalize(d);
Expand Down
3 changes: 3 additions & 0 deletions hw/xbox/nv2a/pgraph/pgraph.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ typedef struct PGRAPHState {
bool sync_pending;
QemuEvent sync_complete;

bool framebuffer_in_use;
QemuCond framebuffer_released;

unsigned int surface_scale_factor;
uint8_t *scale_buf;

Expand Down
4 changes: 0 additions & 4 deletions hw/xbox/nv2a/pgraph/vk/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ void pgraph_vk_set_surface_scale_factor(NV2AState *d, unsigned int scale)
{
g_config.display.quality.surface_scale = scale < 1 ? 1 : scale;

qemu_mutex_unlock_iothread();

qemu_mutex_lock(&d->pfifo.lock);
qatomic_set(&d->pfifo.halt, true);
qemu_mutex_unlock(&d->pfifo.lock);
Expand Down Expand Up @@ -65,8 +63,6 @@ void pgraph_vk_set_surface_scale_factor(NV2AState *d, unsigned int scale)
qatomic_set(&d->pfifo.halt, false);
pfifo_kick(d);
qemu_mutex_unlock(&d->pfifo.lock);

qemu_mutex_lock_iothread();
}

unsigned int pgraph_vk_get_surface_scale_factor(NV2AState *d)
Expand Down
1 change: 1 addition & 0 deletions ui/xemu.c
Original file line number Diff line number Diff line change
Expand Up @@ -1209,6 +1209,7 @@ void sdl2_gl_refresh(DisplayChangeListener *dcl)
qemu_mutex_unlock_main_loop();

glFinish();
nv2a_release_framebuffer_surface();
SDL_GL_SwapWindow(scon->real_window);

/* VGA update (see note above) + vblank */
Expand Down

0 comments on commit da59a60

Please sign in to comment.