mirror of https://github.com/xemu-project/xemu.git
initial support for paletted textures
This commit is contained in:
parent
9dea936168
commit
94b2c7ea7c
113
hw/xbox/nv2a.c
113
hw/xbox/nv2a.c
|
@ -434,6 +434,17 @@
|
|||
#define NV_PGRAPH_TEXOFFSET1 0x00001A28
|
||||
#define NV_PGRAPH_TEXOFFSET2 0x00001A2C
|
||||
#define NV_PGRAPH_TEXOFFSET3 0x00001A30
|
||||
#define NV_PGRAPH_TEXPALETTE0 0x00001A34
|
||||
# define NV_PGRAPH_TEXPALETTE0_CONTEXT_DMA (1 << 0)
|
||||
# define NV_PGRAPH_TEXPALETTE0_LENGTH 0x0000000C
|
||||
# define NV_PGRAPH_TEXPALETTE0_LENGTH_256 0
|
||||
# define NV_PGRAPH_TEXPALETTE0_LENGTH_128 1
|
||||
# define NV_PGRAPH_TEXPALETTE0_LENGTH_64 2
|
||||
# define NV_PGRAPH_TEXPALETTE0_LENGTH_32 3
|
||||
# define NV_PGRAPH_TEXPALETTE0_OFFSET 0xFFFFFFC0
|
||||
#define NV_PGRAPH_TEXPALETTE1 0x00001A38
|
||||
#define NV_PGRAPH_TEXPALETTE2 0x00001A3C
|
||||
#define NV_PGRAPH_TEXPALETTE3 0x00001A40
|
||||
#define NV_PGRAPH_ZSTENCILCLEARVALUE 0x00001A88
|
||||
#define NV_PGRAPH_ZCLIPMAX 0x00001ABC
|
||||
#define NV_PGRAPH_ZCLIPMIN 0x00001A90
|
||||
|
@ -795,6 +806,14 @@
|
|||
# define NV097_SET_TEXTURE_IMAGE_RECT 0x00971B1C
|
||||
# define NV097_SET_TEXTURE_IMAGE_RECT_WIDTH 0xFFFF0000
|
||||
# define NV097_SET_TEXTURE_IMAGE_RECT_HEIGHT 0x0000FFFF
|
||||
# define NV097_SET_TEXTURE_PALETTE 0x00971B20
|
||||
# define NV097_SET_TEXTURE_PALETTE_CONTEXT_DMA (1 << 0)
|
||||
# define NV097_SET_TEXTURE_PALETTE_LENGTH 0x0000000C
|
||||
# define NV097_SET_TEXTURE_PALETTE_LENGTH_256 0
|
||||
# define NV097_SET_TEXTURE_PALETTE_LENGTH_128 1
|
||||
# define NV097_SET_TEXTURE_PALETTE_LENGTH_64 2
|
||||
# define NV097_SET_TEXTURE_PALETTE_LENGTH_32 3
|
||||
# define NV097_SET_TEXTURE_PALETTE_OFFSET 0xFFFFFFC0
|
||||
# define NV097_SET_SEMAPHORE_OFFSET 0x00971D6C
|
||||
# define NV097_BACK_END_WRITE_SEMAPHORE_RELEASE 0x00971D70
|
||||
# define NV097_SET_ZSTENCIL_CLEAR_VALUE 0x00971D8C
|
||||
|
@ -961,9 +980,9 @@ static const ColorFormatInfo kelvin_color_format_map[66] = {
|
|||
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X8R8G8B8] =
|
||||
{4, false, GL_RGB8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
|
||||
|
||||
/* TODO: 8-bit palettized textures */
|
||||
/* paletted texture */
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8] =
|
||||
{1, false, GL_R8, GL_RED, GL_UNSIGNED_BYTE},
|
||||
{1, false, GL_RGBA8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV},
|
||||
|
||||
[NV097_SET_TEXTURE_FORMAT_COLOR_L_DXT1_A1R5G5B5] =
|
||||
{4, false, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0, GL_RGBA},
|
||||
|
@ -1184,6 +1203,7 @@ typedef struct TextureKey {
|
|||
TextureShape state;
|
||||
uint64_t data_hash;
|
||||
uint8_t* texture_data;
|
||||
uint8_t* palette_data;
|
||||
} TextureKey;
|
||||
|
||||
typedef struct TextureBinding {
|
||||
|
@ -1810,8 +1830,31 @@ static unsigned int pgraph_bind_inline_array(NV2AState *d)
|
|||
return index_count;
|
||||
}
|
||||
|
||||
static uint8_t* convert_texture_data(const TextureShape s,
|
||||
uint8_t *data,
|
||||
const uint8_t *palette_data,
|
||||
unsigned int width, unsigned int height,
|
||||
unsigned int pitch)
|
||||
{
|
||||
if (s.color_format == NV097_SET_TEXTURE_FORMAT_COLOR_SZ_I8_A8R8G8B8) {
|
||||
uint8_t* converted_data = g_malloc(width * height * 4);
|
||||
int x, y;
|
||||
for (y = 0; y < height; y++) {
|
||||
for (x = 0; x < width; x++) {
|
||||
uint8_t index = data[y * pitch + x];
|
||||
uint32_t color = *(uint32_t*)(palette_data + index * 4);
|
||||
*(uint32_t*)(converted_data + y * width * 4 + x * 4) = color;
|
||||
}
|
||||
}
|
||||
return converted_data;
|
||||
} else {
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
||||
static TextureBinding* generate_texture(const TextureShape s,
|
||||
const uint8_t *texture_data)
|
||||
const uint8_t *texture_data,
|
||||
const uint8_t *palette_data)
|
||||
{
|
||||
ColorFormatInfo f = kelvin_color_format_map[s.color_format];
|
||||
|
||||
|
@ -1880,11 +1923,18 @@ static TextureBinding* generate_texture(const TextureShape s,
|
|||
unswizzle_rect(texture_data, width, height,
|
||||
unswizzled, pitch, f.bytes_per_pixel);
|
||||
|
||||
uint8_t *converted = convert_texture_data(s, unswizzled,
|
||||
palette_data,
|
||||
width, height, pitch);
|
||||
|
||||
glTexImage2D(gl_target, level, f.gl_internal_format,
|
||||
width, height, 0,
|
||||
f.gl_format, f.gl_type,
|
||||
unswizzled);
|
||||
converted);
|
||||
|
||||
if (converted != unswizzled) {
|
||||
g_free(converted);
|
||||
}
|
||||
g_free(unswizzled);
|
||||
|
||||
texture_data += width * height * f.bytes_per_pixel;
|
||||
|
@ -1925,7 +1975,9 @@ static gboolean texture_key_equal(gconstpointer a, gconstpointer b)
|
|||
static gpointer texture_key_retrieve(gpointer key, gpointer user_data)
|
||||
{
|
||||
const TextureKey *k = key;
|
||||
TextureBinding *v = generate_texture(k->state, k->texture_data);
|
||||
TextureBinding *v = generate_texture(k->state,
|
||||
k->texture_data,
|
||||
k->palette_data);
|
||||
return v;
|
||||
}
|
||||
static void texture_key_destroy(gpointer data)
|
||||
|
@ -1987,6 +2039,23 @@ static void pgraph_bind_textures(NV2AState *d)
|
|||
|
||||
unsigned int offset = pg->regs[NV_PGRAPH_TEXOFFSET0 + i*4];
|
||||
|
||||
uint32_t palette = pg->regs[NV_PGRAPH_TEXPALETTE0 + i*4];
|
||||
unsigned int palette_dma_select =
|
||||
GET_MASK(palette, NV_PGRAPH_TEXPALETTE0_CONTEXT_DMA);
|
||||
unsigned int palette_length_index =
|
||||
GET_MASK(palette, NV_PGRAPH_TEXPALETTE0_LENGTH);
|
||||
unsigned int palette_offset =
|
||||
palette & NV_PGRAPH_TEXPALETTE0_OFFSET;
|
||||
|
||||
unsigned int palette_length = 0;
|
||||
switch (palette_length_index) {
|
||||
case NV_PGRAPH_TEXPALETTE0_LENGTH_256: palette_length = 256; break;
|
||||
case NV_PGRAPH_TEXPALETTE0_LENGTH_128: palette_length = 128; break;
|
||||
case NV_PGRAPH_TEXPALETTE0_LENGTH_64: palette_length = 64; break;
|
||||
case NV_PGRAPH_TEXPALETTE0_LENGTH_32: palette_length = 32; break;
|
||||
default: assert(false); break;
|
||||
}
|
||||
|
||||
if (dimensionality != 2) continue;
|
||||
|
||||
glActiveTexture(GL_TEXTURE0 + i);
|
||||
|
@ -2039,6 +2108,16 @@ static void pgraph_bind_textures(NV2AState *d)
|
|||
assert(offset < dma_len);
|
||||
texture_data += offset;
|
||||
|
||||
hwaddr palette_dma_len;
|
||||
uint8_t *palette_data;
|
||||
if (palette_dma_select) {
|
||||
palette_data = nv_dma_map(d, pg->dma_b, &palette_dma_len);
|
||||
} else {
|
||||
palette_data = nv_dma_map(d, pg->dma_a, &palette_dma_len);
|
||||
}
|
||||
assert(palette_offset < palette_dma_len);
|
||||
palette_data += palette_offset;
|
||||
|
||||
NV2A_DPRINTF(" - 0x%tx\n", texture_data - d->vram_ptr);
|
||||
|
||||
size_t length = 0;
|
||||
|
@ -2068,8 +2147,10 @@ static void pgraph_bind_textures(NV2AState *d)
|
|||
#ifdef USE_TEXTURE_CACHE
|
||||
TextureKey key = {
|
||||
.state = state,
|
||||
.data_hash = fast_hash(texture_data, length, 1000),
|
||||
.data_hash = fast_hash(texture_data, length, 1000)
|
||||
^ fnv_hash(palette_data, palette_length),
|
||||
.texture_data = texture_data,
|
||||
.palette_data = palette_data,
|
||||
};
|
||||
|
||||
gpointer cache_key = g_malloc(sizeof(TextureKey));
|
||||
|
@ -2079,7 +2160,8 @@ static void pgraph_bind_textures(NV2AState *d)
|
|||
assert(binding);
|
||||
binding->refcnt++;
|
||||
#else
|
||||
TextureBinding *binding = generate_texture(state, texture_data);
|
||||
TextureBinding *binding = generate_texture(state,
|
||||
texture_data, palette_data);
|
||||
#endif
|
||||
|
||||
glBindTexture(binding->gl_target, binding->gl_texture);
|
||||
|
@ -4147,6 +4229,23 @@ static void pgraph_method(NV2AState *d,
|
|||
pg->regs[NV_PGRAPH_TEXIMAGERECT0 + slot * 4] = parameter;
|
||||
pg->texture_dirty[slot] = true;
|
||||
break;
|
||||
CASE_4(NV097_SET_TEXTURE_PALETTE, 64): {
|
||||
slot = (class_method - NV097_SET_TEXTURE_IMAGE_RECT) / 64;
|
||||
bool dma_select =
|
||||
GET_MASK(parameter, NV097_SET_TEXTURE_PALETTE_CONTEXT_DMA) == 1;
|
||||
unsigned int length =
|
||||
GET_MASK(parameter, NV097_SET_TEXTURE_PALETTE_LENGTH);
|
||||
unsigned int offset =
|
||||
GET_MASK(parameter, NV097_SET_TEXTURE_PALETTE_OFFSET);
|
||||
|
||||
uint32_t *reg = &pg->regs[NV_PGRAPH_TEXPALETTE0 + slot * 4];
|
||||
SET_MASK(*reg, NV_PGRAPH_TEXPALETTE0_CONTEXT_DMA, dma_select);
|
||||
SET_MASK(*reg, NV_PGRAPH_TEXPALETTE0_LENGTH, length);
|
||||
SET_MASK(*reg, NV_PGRAPH_TEXPALETTE0_OFFSET, offset);
|
||||
|
||||
pg->texture_dirty[slot] = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case NV097_ARRAY_ELEMENT16:
|
||||
assert(pg->inline_elements_length < NV2A_MAX_BATCH_LENGTH);
|
||||
|
|
Loading…
Reference in New Issue