Skip to content

Commit

Permalink
nv2a: Fall back to VGA path on framebuffer surface format mismatch.
Browse files Browse the repository at this point in the history
Handles cases where a surface containing the framebuffer uses a format that
does not match the VGA configuration and thus cannot directly represent the
framebuffer contents.

Fixes #652

[Tests](https://github.com/abaire/nxdk_pgraph_tests/blob/main/src/tests/antialiasing_tests.cpp)
[HW results](https://github.com/abaire/nxdk_pgraph_tests_golden_results/wiki/Results-Antialiasing_tests)
  • Loading branch information
abaire committed Jul 1, 2022
1 parent db389b1 commit 8b179d7
Showing 1 changed file with 29 additions and 9 deletions.
38 changes: 29 additions & 9 deletions hw/xbox/nv2a/pgraph.c
Original file line number Diff line number Diff line change
Expand Up @@ -5267,6 +5267,18 @@ const uint8_t *nv2a_get_dac_palette(void)
return g_nv2a->puserdac.palette;
}

static void pgraph_download_overlapping_surfaces(NV2AState *d, hwaddr start, hwaddr end) {
SurfaceBinding *surface;
QTAILQ_FOREACH (surface, &d->pgraph.surfaces, entry) {
hwaddr surf_vram_end = surface->vram_addr + surface->size - 1;
bool overlapping = !(surface->vram_addr >= end ||
start >= surf_vram_end);
if (overlapping) {
pgraph_download_surface_data_if_dirty(d, surface);
}
}
}

int nv2a_get_framebuffer_surface(void)
{
NV2AState *d = g_nv2a;
Expand All @@ -5276,12 +5288,27 @@ int nv2a_get_framebuffer_surface(void)
// FIXME: Possible race condition with pgraph, consider lock
uint32_t pline_offset, pstart_addr, pline_compare;
d->vga.get_offsets(&d->vga, &pline_offset, &pstart_addr, &pline_compare);
SurfaceBinding *surface = pgraph_surface_get_within(d, d->pcrtc.start + pline_offset);
const hwaddr framebuffer = d->pcrtc.start + pline_offset;
SurfaceBinding *surface = pgraph_surface_get_within(d, framebuffer);
if (surface == NULL || !surface->color) {
qemu_mutex_unlock(&d->pfifo.lock);
return 0;
}

if (surface->width != d->vga.last_scr_width
|| surface->height != d->vga.last_scr_height
|| surface->pitch != surface->width * surface->fmt.bytes_per_pixel) {

// Writeback any surfaces that overlap the framebuffer.
unsigned int length =
d->vga.last_scr_width * d->vga.last_scr_height * 4;
hwaddr framebuffer_end = framebuffer + length - 1;
pgraph_download_overlapping_surfaces(d, framebuffer, framebuffer_end);

qemu_mutex_unlock(&d->pfifo.lock);
return 0;
}

assert(surface->color);
assert(surface->fmt.gl_attachment == GL_COLOR_ATTACHMENT0);
assert(surface->fmt.gl_format == GL_RGBA
Expand Down Expand Up @@ -6623,14 +6650,7 @@ static void pgraph_bind_textures(NV2AState *d)

// Writeback any surfaces which this texture may index
hwaddr tex_vram_end = texture_vram_offset + length - 1;
QTAILQ_FOREACH(surface, &d->pgraph.surfaces, entry) {
hwaddr surf_vram_end = surface->vram_addr + surface->size - 1;
bool overlapping = !(surface->vram_addr >= tex_vram_end
|| texture_vram_offset >= surf_vram_end);
if (overlapping) {
pgraph_download_surface_data_if_dirty(d, surface);
}
}
pgraph_download_overlapping_surfaces(d, texture_vram_offset, tex_vram_end);
}

TextureKey key;
Expand Down

0 comments on commit 8b179d7

Please sign in to comment.