From d91e6d304f4ce23a3cf1601822bdbc48fe29fd75 Mon Sep 17 00:00:00 2001 From: Matt Borgerson Date: Sat, 8 Jan 2022 02:04:17 -0700 Subject: [PATCH] nv2a: Refactor blit operation logic --- hw/xbox/nv2a/pgraph.c | 183 +++++++++++++++++------------------------- 1 file changed, 72 insertions(+), 111 deletions(-) diff --git a/hw/xbox/nv2a/pgraph.c b/hw/xbox/nv2a/pgraph.c index 6df15c3564..d5335c7579 100644 --- a/hw/xbox/nv2a/pgraph.c +++ b/hw/xbox/nv2a/pgraph.c @@ -775,24 +775,26 @@ static void pgraph_image_blit(NV2AState *d) } hwaddr source_dma_len, dest_dma_len; - uint8_t *source, *dest; - source = (uint8_t *) nv_dma_map(d, context_surfaces->dma_image_source, - &source_dma_len); + uint8_t *source = (uint8_t *)nv_dma_map( + d, context_surfaces->dma_image_source, &source_dma_len); assert(context_surfaces->source_offset < source_dma_len); source += context_surfaces->source_offset; - dest = (uint8_t *) nv_dma_map(d, context_surfaces->dma_image_dest, - &dest_dma_len); + uint8_t *dest = (uint8_t *)nv_dma_map(d, context_surfaces->dma_image_dest, + &dest_dma_len); assert(context_surfaces->dest_offset < dest_dma_len); dest += context_surfaces->dest_offset; - SurfaceBinding *surf_src = pgraph_surface_get(d, source - d->vram_ptr); + hwaddr source_addr = source - d->vram_ptr; + hwaddr dest_addr = dest - d->vram_ptr; + + SurfaceBinding *surf_src = pgraph_surface_get(d, source_addr); if (surf_src) { pgraph_download_surface_data(d, surf_src, true); } - SurfaceBinding *surf_dest = pgraph_surface_get(d, dest - d->vram_ptr); + SurfaceBinding *surf_dest = pgraph_surface_get(d, dest_addr); if (surf_dest) { if (image_blit->height < surf_dest->height || image_blit->width < surf_dest->width) { @@ -801,127 +803,86 @@ static void pgraph_image_blit(NV2AState *d) surf_dest->upload_pending = true; } - uint32_t color_format = context_surfaces->color_format; - uint8_t alpha_override = 0; - bool needs_alpha_patching = false; - if (color_format == NV062_SET_COLOR_FORMAT_LE_X8R8G8B8) { - // XBOX hardware forces alpha to 0xFF for any pixel modified by the blit. - alpha_override = 0xFF; - needs_alpha_patching = true; - } else if (color_format == NV062_SET_COLOR_FORMAT_LE_X8R8G8B8_Z8R8G8B8) { - alpha_override = 0x00; - needs_alpha_patching = true; - } + hwaddr source_offset = image_blit->in_y * context_surfaces->source_pitch + + image_blit->in_x * bytes_per_pixel; + hwaddr dest_offset = image_blit->out_y * context_surfaces->dest_pitch + + image_blit->out_x * bytes_per_pixel; + + hwaddr source_size = + (image_blit->height - 1) * context_surfaces->source_pitch + + image_blit->width * bytes_per_pixel; + hwaddr dest_size = (image_blit->height - 1) * context_surfaces->dest_pitch + + image_blit->width * bytes_per_pixel; + + /* FIXME: What does hardware do in this case? */ + assert(source_addr + source_offset + source_size <= + memory_region_size(d->vram)); + assert(dest_addr + dest_offset + dest_size <= memory_region_size(d->vram)); + + uint8_t *source_row = source + source_offset; + uint8_t *dest_row = dest + dest_offset; if (image_blit->operation == NV09F_SET_OPERATION_SRCCOPY) { NV2A_GL_DPRINTF(true, "NV09F_SET_OPERATION_SRCCOPY"); - NV2A_DPRINTF(" - 0x%tx -> 0x%tx\n", source - d->vram_ptr, - dest - d->vram_ptr); - - uint32_t bytes_per_row = image_blit->width * bytes_per_pixel; - for (int y = 0; y < image_blit->height; y++) { - uint8_t *source_row = source - + (image_blit->in_y + y) * context_surfaces->source_pitch - + image_blit->in_x * bytes_per_pixel; - - uint8_t *dest_row = dest - + (image_blit->out_y + y) * context_surfaces->dest_pitch - + image_blit->out_x * bytes_per_pixel; - - memmove(dest_row, source_row, bytes_per_row); - } - - if (needs_alpha_patching) { - for (int y = 0; y < image_blit->height; y++) { - uint8_t *dest_row = - dest - + (image_blit->out_y + y) * context_surfaces->dest_pitch - + image_blit->out_x * bytes_per_pixel; - dest_row += 3; - for (int x = 0; x < image_blit->width; x++) { - *dest_row = alpha_override; - dest_row += 4; - } - } + for (unsigned int y = 0; y < image_blit->height; y++) { + memmove(dest_row, source_row, image_blit->width * bytes_per_pixel); + source_row += context_surfaces->source_pitch; + dest_row += context_surfaces->dest_pitch; } } else if (image_blit->operation == NV09F_SET_OPERATION_BLEND_AND) { NV2A_GL_DPRINTF(true, "NV09F_SET_OPERATION_BLEND_AND"); - NV2A_DPRINTF(" - 0x%tx -> 0x%tx\n", source - d->vram_ptr, - dest - d->vram_ptr); - - uint32_t bytes_per_row = image_blit->width * bytes_per_pixel; - static const uint32_t max_beta_mult = 0x7f80; + uint32_t max_beta_mult = 0x7f80; uint32_t beta_mult = beta->beta >> 16; uint32_t inv_beta_mult = max_beta_mult - beta_mult; - - if (needs_alpha_patching) { - for (int y = 0; y < image_blit->height; y++) { - uint8_t *source_row = - source - + (image_blit->in_y + y) * context_surfaces->source_pitch - + image_blit->in_x * bytes_per_pixel; - - uint8_t *dest_row = - dest - + (image_blit->out_y + y) * context_surfaces->dest_pitch - + image_blit->out_x * bytes_per_pixel; - - for (int x = 0; x < image_blit->width; ++x) { - uint32_t a; - uint32_t b; - a = *source_row++ * beta_mult; - b = *dest_row * inv_beta_mult; - *dest_row++ = (a + b) / max_beta_mult; - - a = *source_row++ * beta_mult; - b = *dest_row * inv_beta_mult; - *dest_row++ = (a + b) / max_beta_mult; - - a = *source_row++ * beta_mult; - b = *dest_row * inv_beta_mult; - *dest_row++ = (a + b) / max_beta_mult; - - *dest_row++ = alpha_override; - ++source_row; - } - } - } else { - for (int y = 0; y < image_blit->height; y++) { - uint8_t *source_row = - source - + (image_blit->in_y + y) * context_surfaces->source_pitch - + image_blit->in_x * bytes_per_pixel; - - uint8_t *dest_row = - dest - + (image_blit->out_y + y) * context_surfaces->dest_pitch - + image_blit->out_x * bytes_per_pixel; - - for (int x = 0; x < bytes_per_row; ++x, ++source_row) { - uint32_t a = *source_row * beta_mult; - uint32_t b = *dest_row * inv_beta_mult; - *dest_row = (a + b) / max_beta_mult; + for (unsigned int y = 0; y < image_blit->height; y++) { + for (unsigned int x = 0; x < image_blit->width; x++) { + for (unsigned int ch = 0; ch < 3; ch++) { + uint32_t a = source_row[x * 4 + ch] * beta_mult; + uint32_t b = dest_row[x * 4 + ch] * inv_beta_mult; + dest_row[x * 4 + ch] = (a + b) / max_beta_mult; } } + source_row += context_surfaces->source_pitch; + dest_row += context_surfaces->dest_pitch; } } else { - fprintf(stderr, "Unknown blit operation: 0x%x\n", image_blit->operation); + fprintf(stderr, "Unknown blit operation: 0x%x\n", + image_blit->operation); assert(false && "Unknown blit operation"); } - uint32_t dest_start = image_blit->out_y * context_surfaces->dest_pitch - + image_blit->out_x; + NV2A_DPRINTF(" - 0x%tx -> 0x%tx\n", source_addr, dest_addr); - uint32_t dirty_size = - ((image_blit->height - 1) * context_surfaces->dest_pitch) - + image_blit->width * bytes_per_pixel; - memory_region_set_client_dirty(d->vram, - (dest - d->vram_ptr + dest_start), - dirty_size, + bool needs_alpha_patching; + uint8_t alpha_override; + switch (context_surfaces->color_format) { + case NV062_SET_COLOR_FORMAT_LE_X8R8G8B8: + needs_alpha_patching = true; + alpha_override = 0xff; + break; + case NV062_SET_COLOR_FORMAT_LE_X8R8G8B8_Z8R8G8B8: + needs_alpha_patching = true; + alpha_override = 0; + break; + default: + needs_alpha_patching = false; + alpha_override = 0; + } + + if (needs_alpha_patching) { + dest_row = dest + dest_offset; + for (unsigned int y = 0; y < image_blit->height; y++) { + for (unsigned int x = 0; x < image_blit->width; x++) { + dest_row[x * 4 + 3] = alpha_override; + } + dest_row += context_surfaces->dest_pitch; + } + } + + dest_addr += dest_offset; + memory_region_set_client_dirty(d->vram, dest_addr, dest_size, DIRTY_MEMORY_VGA); - memory_region_set_client_dirty(d->vram, - (dest - d->vram_ptr + dest_start), - dirty_size, + memory_region_set_client_dirty(d->vram, dest_addr, dest_size, DIRTY_MEMORY_NV2A_TEX); }