add support for some signed texture formats

This commit is contained in:
oltolm 2025-01-26 20:39:50 +01:00
parent 57cdee770e
commit 195324558e
4 changed files with 64 additions and 24 deletions

View File

@ -222,7 +222,7 @@ static const ColorFormatInfo kelvin_color_format_gl_map[66] = {
{GL_RED, GL_RED, GL_RED, GL_GREEN}},
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R6G5B5] =
{2, false, GL_RGB8_SNORM, GL_RGB, GL_BYTE}, /* FIXME: This might be signed */
{2, false, GL_RGB8, GL_RGB, GL_UNSIGNED_BYTE},
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_G8B8] =
{2, false, GL_RG8, GL_RG, GL_UNSIGNED_BYTE,
{GL_RED, GL_GREEN, GL_RED, GL_GREEN}},
@ -276,6 +276,17 @@ static const ColorFormatInfo kelvin_color_format_gl_map[66] = {
{4, true, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8}
};
static const ColorFormatInfo kelvin_signed_color_format_gl_map[66] = {
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R6G5B5] =
{2, false, GL_RGB8_SNORM, GL_RGB, GL_BYTE},
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_G8B8] =
{2, false, GL_RG8_SNORM, GL_RG, GL_BYTE,
{GL_RED, GL_GREEN, GL_RED, GL_GREEN}},
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R8B8] =
{2, false, GL_RG8_SNORM, GL_RG, GL_BYTE,
{GL_GREEN, GL_RED, GL_RED, GL_GREEN}},
};
typedef struct SurfaceFormatInfo {
unsigned int bytes_per_pixel;
GLint gl_internal_format;
@ -319,4 +330,12 @@ static const SurfaceFormatInfo kelvin_surface_zeta_fixed_format_gl_map[] = {
{4, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH_STENCIL_ATTACHMENT},
};
static const uint32_t kelvin_signed_format_mask_gl_map[66] = {
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R6G5B5] =
NV_PGRAPH_TEXFILTER0_RSIGNED | NV_PGRAPH_TEXFILTER0_GSIGNED | NV_PGRAPH_TEXFILTER0_BSIGNED,
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_G8B8] =
NV_PGRAPH_TEXFILTER0_GSIGNED | NV_PGRAPH_TEXFILTER0_BSIGNED,
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R8B8] =
NV_PGRAPH_TEXFILTER0_RSIGNED | NV_PGRAPH_TEXFILTER0_BSIGNED
};
#endif

View File

@ -37,6 +37,7 @@
#include "gloffscreen.h"
#include "constants.h"
#include <stdint.h>
typedef struct SurfaceBinding {
QTAILQ_ENTRY(SurfaceBinding) entry;
@ -271,7 +272,7 @@ void pgraph_gl_init_buffers(NV2AState *d);
void pgraph_gl_finalize_buffers(PGRAPHState *pg);
void pgraph_gl_process_pending_downloads(NV2AState *d);
void pgraph_gl_reload_surface_scale_factor(PGRAPHState *pg);
void pgraph_gl_render_surface_to_texture(NV2AState *d, SurfaceBinding *surface, TextureBinding *texture, TextureShape *texture_shape, int texture_unit);
void pgraph_gl_render_surface_to_texture(NV2AState *d, SurfaceBinding *surface, TextureBinding *texture, TextureShape *texture_shape, int texture_unit, uint32_t filter);
void pgraph_gl_set_surface_dirty(PGRAPHState *pg, bool color, bool zeta);
void pgraph_gl_surface_download_if_dirty(NV2AState *d, SurfaceBinding *surface);
SurfaceBinding *pgraph_gl_surface_get(NV2AState *d, hwaddr addr);

View File

@ -25,6 +25,7 @@
#include "hw/xbox/nv2a/pgraph/swizzle.h"
#include "debug.h"
#include "renderer.h"
#include <stdint.h>
static void surface_download(NV2AState *d, SurfaceBinding *surface, bool force);
static void surface_download_to_buffer(NV2AState *d, SurfaceBinding *surface,
@ -280,11 +281,16 @@ static void render_surface_to_texture_slow(NV2AState *d,
SurfaceBinding *surface,
TextureBinding *texture,
TextureShape *texture_shape,
int texture_unit)
int texture_unit,
uint32_t filter)
{
PGRAPHState *pg = &d->pgraph;
const ColorFormatInfo *f = &kelvin_color_format_gl_map[texture_shape->color_format];
ColorFormatInfo f = kelvin_color_format_gl_map[texture_shape->color_format];
uint32_t mask = kelvin_signed_format_mask_gl_map[texture_shape->color_format];
if (mask && (filter & mask) == mask)
f = kelvin_signed_color_format_gl_map[texture_shape->color_format];
assert(texture_shape->color_format < ARRAY_SIZE(kelvin_color_format_gl_map));
nv2a_profile_inc_counter(NV2A_PROF_SURF_TO_TEX_FALLBACK);
@ -304,8 +310,8 @@ static void render_surface_to_texture_slow(NV2AState *d,
height = texture_shape->height;
pgraph_apply_scaling_factor(pg, &width, &height);
glTexImage2D(texture->gl_target, 0, f->gl_internal_format, width, height, 0,
f->gl_format, f->gl_type, buf);
glTexImage2D(texture->gl_target, 0, f.gl_internal_format, width, height, 0,
f.gl_format, f.gl_type, buf);
g_free(buf);
glBindTexture(texture->gl_target, texture->gl_texture);
}
@ -317,20 +323,23 @@ static void render_surface_to_texture_slow(NV2AState *d,
void pgraph_gl_render_surface_to_texture(NV2AState *d, SurfaceBinding *surface,
TextureBinding *texture,
TextureShape *texture_shape,
int texture_unit)
int texture_unit,
uint32_t filter)
{
PGRAPHState *pg = &d->pgraph;
PGRAPHGLState *r = pg->gl_renderer_state;
const ColorFormatInfo *f =
&kelvin_color_format_gl_map[texture_shape->color_format];
ColorFormatInfo f = kelvin_color_format_gl_map[texture_shape->color_format];
uint32_t mask = kelvin_signed_format_mask_gl_map[texture_shape->color_format];
if (mask && (filter & mask) == mask)
f = kelvin_signed_color_format_gl_map[texture_shape->color_format];
assert(texture_shape->color_format < ARRAY_SIZE(kelvin_color_format_gl_map));
nv2a_profile_inc_counter(NV2A_PROF_SURF_TO_TEX);
if (!surface_to_texture_can_fastpath(surface, texture_shape)) {
render_surface_to_texture_slow(d, surface, texture,
texture_shape, texture_unit);
texture_shape, texture_unit, filter);
return;
}
@ -342,8 +351,8 @@ void pgraph_gl_render_surface_to_texture(NV2AState *d, SurfaceBinding *surface,
glTexParameteri(texture->gl_target, GL_TEXTURE_BASE_LEVEL, 0);
glTexParameteri(texture->gl_target, GL_TEXTURE_MAX_LEVEL, 0);
glTexParameteri(texture->gl_target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexImage2D(texture->gl_target, 0, f->gl_internal_format, width, height, 0,
f->gl_format, f->gl_type, NULL);
glTexImage2D(texture->gl_target, 0, f.gl_internal_format, width, height, 0,
f.gl_format, f.gl_type, NULL);
glBindTexture(texture->gl_target, 0);
render_surface_to(d, surface, texture_unit, texture->gl_target,
texture->gl_texture, width, height);

View File

@ -24,10 +24,12 @@
#include "hw/xbox/nv2a/pgraph/swizzle.h"
#include "hw/xbox/nv2a/pgraph/s3tc.h"
#include "hw/xbox/nv2a/pgraph/texture.h"
#include "constants.h"
#include "debug.h"
#include "renderer.h"
#include <stdint.h>
static TextureBinding* generate_texture(const TextureShape s, const uint8_t *texture_data, const uint8_t *palette_data);
static TextureBinding* generate_texture(const TextureShape s, const uint8_t *texture_data, const uint8_t *palette_data, uint32_t filter);
static void texture_binding_destroy(gpointer data);
struct pgraph_texture_possibly_dirty_struct {
@ -343,7 +345,7 @@ void pgraph_gl_bind_textures(NV2AState *d)
if (key_out->binding == NULL) {
// Must create the texture
key_out->binding = generate_texture(state, texture_data, palette_data);
key_out->binding = generate_texture(state, texture_data, palette_data, filter);
key_out->binding->data_hash = tex_data_hash;
key_out->binding->scale = 1;
} else {
@ -360,7 +362,7 @@ void pgraph_gl_bind_textures(NV2AState *d)
trace_nv2a_pgraph_surface_render_to_texture(
surface->vram_addr, surface->width, surface->height);
pgraph_gl_render_surface_to_texture(d, surface, binding, &state, i);
pgraph_gl_render_surface_to_texture(d, surface, binding, &state, i, filter);
binding->draw_time = surface->draw_time;
binding->scale = pg->surface_scale_factor;
}
@ -403,9 +405,14 @@ gl_internal_format_to_s3tc_enum(GLint gl_internal_format)
static void upload_gl_texture(GLenum gl_target,
const TextureShape s,
const uint8_t *texture_data,
const uint8_t *palette_data)
const uint8_t *palette_data,
uint32_t filter)
{
ColorFormatInfo f = kelvin_color_format_gl_map[s.color_format];
uint32_t mask = kelvin_signed_format_mask_gl_map[s.color_format];
if (mask && (filter & mask) == mask)
f = kelvin_signed_color_format_gl_map[s.color_format];
nv2a_profile_inc_counter(NV2A_PROF_TEX_UPLOAD);
unsigned int adjusted_width = s.width;
@ -620,9 +627,13 @@ static void upload_gl_texture(GLenum gl_target,
static TextureBinding* generate_texture(const TextureShape s,
const uint8_t *texture_data,
const uint8_t *palette_data)
const uint8_t *palette_data,
uint32_t filter)
{
ColorFormatInfo f = kelvin_color_format_gl_map[s.color_format];
uint32_t mask = kelvin_signed_format_mask_gl_map[s.color_format];
if (mask && (filter & mask) == mask)
f = kelvin_signed_color_format_gl_map[s.color_format];
/* Create a new opengl texture */
GLuint gl_texture;
@ -690,19 +701,19 @@ static TextureBinding* generate_texture(const TextureShape s,
length = (length + NV2A_CUBEMAP_FACE_ALIGNMENT - 1) & ~(NV2A_CUBEMAP_FACE_ALIGNMENT - 1);
upload_gl_texture(GL_TEXTURE_CUBE_MAP_POSITIVE_X,
s, texture_data + 0 * length, palette_data);
s, texture_data + 0 * length, palette_data, filter);
upload_gl_texture(GL_TEXTURE_CUBE_MAP_NEGATIVE_X,
s, texture_data + 1 * length, palette_data);
s, texture_data + 1 * length, palette_data, filter);
upload_gl_texture(GL_TEXTURE_CUBE_MAP_POSITIVE_Y,
s, texture_data + 2 * length, palette_data);
s, texture_data + 2 * length, palette_data, filter);
upload_gl_texture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y,
s, texture_data + 3 * length, palette_data);
s, texture_data + 3 * length, palette_data, filter);
upload_gl_texture(GL_TEXTURE_CUBE_MAP_POSITIVE_Z,
s, texture_data + 4 * length, palette_data);
s, texture_data + 4 * length, palette_data, filter);
upload_gl_texture(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z,
s, texture_data + 5 * length, palette_data);
s, texture_data + 5 * length, palette_data, filter);
} else {
upload_gl_texture(gl_target, s, texture_data, palette_data);
upload_gl_texture(gl_target, s, texture_data, palette_data, filter);
}
/* Linear textures don't support mipmapping */