Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 20 additions & 1 deletion hw/xbox/nv2a/pgraph/gl/constants.h
Original file line number Diff line number Diff line change
Expand Up @@ -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}},
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

R might usually be unsigned. See also the texture data conversion done in, which should change depending on if signs are set or not:

} else if (s.color_format == NV097_SET_TEXTURE_FORMAT_COLOR_SZ_R6G5B5) {
assert(depth == 1); /* FIXME */
size = width * height * 3;
converted_data = g_malloc(size);
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
uint16_t rgb655 = *(uint16_t *)(data + y * row_pitch + x * 2);
int8_t *pixel = (int8_t *)&converted_data[(y * width + x) * 3];
/* Maps 5 bit G and B signed value range to 8 bit
* signed values. R is probably unsigned.
*/
rgb655 ^= (1 << 9) | (1 << 4);
pixel[0] = ((rgb655 & 0xFC00) >> 10) * 0x7F / 0x3F;
pixel[1] = ((rgb655 & 0x03E0) >> 5) * 0xFF / 0x1F - 0x80;
pixel[2] = (rgb655 & 0x001F) * 0xFF / 0x1F - 0x80;
}
}
} else {

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what this code does, I can't do it.

[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
3 changes: 2 additions & 1 deletion hw/xbox/nv2a/pgraph/gl/renderer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include "gloffscreen.h"
#include "constants.h"
#include <stdint.h>

typedef struct SurfaceBinding {
QTAILQ_ENTRY(SurfaceBinding) entry;
Expand Down Expand Up @@ -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);
Expand Down
29 changes: 19 additions & 10 deletions hw/xbox/nv2a/pgraph/gl/surface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);

Expand All @@ -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);
}
Expand All @@ -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;
}

Expand All @@ -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);
Expand Down
35 changes: 23 additions & 12 deletions hw/xbox/nv2a/pgraph/gl/texture.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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 {
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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 */
Expand Down