From f4ba11f180355a9ab17c437ae4ed922ec44a17ee Mon Sep 17 00:00:00 2001 From: Jannik Vogel <email@jannikvogel.de> Date: Sun, 12 Jul 2015 02:25:35 +0200 Subject: [PATCH 1/8] Added first palette texture mode --- hw/xbox/nv2a.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index c2a753dd87..a095270081 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -2092,6 +2092,7 @@ static void pgraph_bind_textures(NV2AState *d) uint32_t ctl_1 = pg->regs[NV_PGRAPH_TEXCTL1_0 + i*4]; uint32_t fmt = pg->regs[NV_PGRAPH_TEXFMT0 + i*4]; uint32_t filter = pg->regs[NV_PGRAPH_TEXFILTER0 + i*4]; + uint32_t palette = pg->regs[NV_PGRAPH_TEXPALETTE0 + i*4]; bool enabled = GET_MASK(ctl_0, NV_PGRAPH_TEXCTL0_0_ENABLE); unsigned int min_mipmap_level = @@ -2125,8 +2126,7 @@ 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 = + bool palette_dma_select = GET_MASK(palette, NV_PGRAPH_TEXPALETTE0_CONTEXT_DMA); unsigned int palette_length_index = GET_MASK(palette, NV_PGRAPH_TEXPALETTE0_LENGTH); @@ -4346,7 +4346,8 @@ static void pgraph_method(NV2AState *d, pg->texture_dirty[slot] = true; break; CASE_4(NV097_SET_TEXTURE_PALETTE, 64): { - slot = (class_method - NV097_SET_TEXTURE_IMAGE_RECT) / 64; + slot = (class_method - NV097_SET_TEXTURE_PALETTE) / 64; + bool dma_select = GET_MASK(parameter, NV097_SET_TEXTURE_PALETTE_CONTEXT_DMA) == 1; unsigned int length = @@ -4362,7 +4363,6 @@ static void pgraph_method(NV2AState *d, pg->texture_dirty[slot] = true; break; } - case NV097_ARRAY_ELEMENT16: assert(pg->inline_elements_length < NV2A_MAX_BATCH_LENGTH); pg->inline_elements[ From 5e0a80b6491cd9cd2a5d9f60d640f5d77d53846f Mon Sep 17 00:00:00 2001 From: Jannik Vogel <email@jannikvogel.de> Date: Sun, 12 Jul 2015 02:26:49 +0200 Subject: [PATCH 2/8] Some new texture formats + YUV conversion=WIP --- hw/xbox/nv2a.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index a095270081..855e3777c8 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -840,6 +840,7 @@ static void gl_debug_label(GLenum target, GLuint name, const char *fmt, ...) # define NV097_SET_TEXTURE_FORMAT_CONTEXT_DMA 0x00000003 # define NV097_SET_TEXTURE_FORMAT_DIMENSIONALITY 0x000000F0 # define NV097_SET_TEXTURE_FORMAT_COLOR 0x0000FF00 +# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_Y8 0x00 # define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A1R5G5B5 0x02 # define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5 0x03 # define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A4R4G4B4 0x04 @@ -855,6 +856,7 @@ static void gl_debug_label(GLenum target, GLuint name, const char *fmt, ...) # define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8 0x19 # define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8 0x1E # define NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8 0x24 +# define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_G8B8 0x28 # define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED 0x2E # define NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FIXED 0x30 # define NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A8B8G8R8 0x3A @@ -1038,6 +1040,8 @@ typedef struct ColorFormatInfo { } ColorFormatInfo; static const ColorFormatInfo kelvin_color_format_map[66] = { + [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_Y8] = + {1, false, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE}, [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A1R5G5B5] = {2, false, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5] = @@ -1071,6 +1075,10 @@ static const ColorFormatInfo kelvin_color_format_map[66] = { {GL_ZERO, GL_ZERO, GL_ZERO, GL_RED}}, [NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8] = {4, true, GL_RGB8, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV}, + + [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_G8B8] = + {2, false, GL_RG8, GL_RG, GL_UNSIGNED_BYTE}, + /* TODO: format conversion */ [NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8] = {4, false, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, @@ -2011,6 +2019,22 @@ static TextureBinding* generate_texture(const TextureShape s, palette_data, width, height, pitch); + if (s.color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8) { + data = g_malloc(height * pitch * 4); + unsigned int y; + for(y = 0; y < height; y++) { + unsigned int x; + for(x = 0; x < pitch; x++) { + uint8_t* pixel = &data[(y * pitch + x) * 4]; + //FIXME: Steal format conversion from video stuff above + pixel[0] = 255; + pixel[1] = 0; + pixel[2] = 255; + pixel[3] = 128; + } + } + } + glTexImage2D(gl_target, level, f.gl_internal_format, width, height, 0, f.gl_format, f.gl_type, From a3d110025e7ad8295f03990c1321f0b964b4086e Mon Sep 17 00:00:00 2001 From: Jannik Vogel <email@jannikvogel.de> Date: Sun, 12 Jul 2015 04:34:13 +0200 Subject: [PATCH 3/8] Fix GL3 error with luminance --- hw/xbox/nv2a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 855e3777c8..8d33168457 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -1041,7 +1041,7 @@ typedef struct ColorFormatInfo { static const ColorFormatInfo kelvin_color_format_map[66] = { [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_Y8] = - {1, false, GL_LUMINANCE8, GL_LUMINANCE, GL_UNSIGNED_BYTE}, + {1, false, GL_R8, GL_RED, GL_UNSIGNED_BYTE}, /* FIXME: luminance, not red */ [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A1R5G5B5] = {2, false, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5] = From 66c4b94a88ba65ad4f8b8f7794d9c838be30e286 Mon Sep 17 00:00:00 2001 From: Jannik Vogel <email@jannikvogel.de> Date: Mon, 13 Jul 2015 18:03:35 +0200 Subject: [PATCH 4/8] Remove spaces --- hw/xbox/nv2a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 8d33168457..a59e3b4c6a 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -4371,7 +4371,7 @@ static void pgraph_method(NV2AState *d, break; CASE_4(NV097_SET_TEXTURE_PALETTE, 64): { slot = (class_method - NV097_SET_TEXTURE_PALETTE) / 64; - + bool dma_select = GET_MASK(parameter, NV097_SET_TEXTURE_PALETTE_CONTEXT_DMA) == 1; unsigned int length = From 33791c74127cbb668363f28ed7bfc788701f97a1 Mon Sep 17 00:00:00 2001 From: Jannik Vogel <email@jannikvogel.de> Date: Mon, 13 Jul 2015 12:22:54 +0200 Subject: [PATCH 5/8] Use new swizzle_mask for luminance textures --- hw/xbox/nv2a.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index a59e3b4c6a..e8e865aabc 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -1041,7 +1041,8 @@ typedef struct ColorFormatInfo { static const ColorFormatInfo kelvin_color_format_map[66] = { [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_Y8] = - {1, false, GL_R8, GL_RED, GL_UNSIGNED_BYTE}, /* FIXME: luminance, not red */ + {1, false, GL_R8, GL_RED, GL_UNSIGNED_BYTE, + {GL_RED, GL_RED, GL_RED, GL_RED}}, [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_A1R5G5B5] = {2, false, GL_RGB5_A1, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV}, [NV097_SET_TEXTURE_FORMAT_COLOR_SZ_X1R5G5B5] = From 285d50f3343dc22e4b3315b716f0b70dd3d65c87 Mon Sep 17 00:00:00 2001 From: Jannik Vogel <email@jannikvogel.de> Date: Mon, 13 Jul 2015 12:14:58 +0200 Subject: [PATCH 6/8] Add uyvy textures --- hw/xbox/nv2a.c | 81 ++++++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index e8e865aabc..5b63c17fa7 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -1082,7 +1082,7 @@ static const ColorFormatInfo kelvin_color_format_map[66] = { /* TODO: format conversion */ [NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8] = - {4, false, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, + {2, true, GL_RGBA8, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV}, [NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_X8_Y24_FIXED] = {4, true, GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8}, [NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_DEPTH_Y16_FIXED] = @@ -1917,6 +1917,27 @@ static unsigned int pgraph_bind_inline_array(NV2AState *d) return index_count; } +static uint8_t cliptobyte(int x) +{ + return (uint8_t)((x < 0) ? 0 : ((x > 255) ? 255 : x)); +} + +static void convert_yuy2_to_rgb(uint8_t* line, unsigned int ix, uint8_t* r, uint8_t* g, uint8_t* b) { + int c, d, e; + c = (int)line[ix * 2] - 16; + if (ix % 2) { + d = (int)line[ix * 2 - 1] - 128; + e = (int)line[ix * 2 + 1] - 128; + } else { + d = (int)line[ix * 2 + 1] - 128; + e = (int)line[ix * 2 + 3] - 128; + } + if (r) { *r = cliptobyte((298 * c + 409 * e + 128) >> 8); } + if (g) { *g = cliptobyte((298 * c - 100 * d - 208 * e + 128) >> 8); } + if (b) { *b = cliptobyte((298 * c + 516 * d + 128) >> 8); } + return; +} + static uint8_t* convert_texture_data(const TextureShape s, uint8_t *data, const uint8_t *palette_data, @@ -1934,6 +1955,18 @@ static uint8_t* convert_texture_data(const TextureShape s, } } return converted_data; + } else if (s.color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8) { + uint8_t* converted_data = g_malloc(width * height * 4); + int x, y; + for (y = 0; y < height; y++) { + uint8_t* line = &data[y * s.width * 2]; + for (x = 0; x < width; x++) { + uint8_t* pixel = &converted_data[(y * s.width + x) * 4]; + convert_yuy2_to_rgb(line,x,&pixel[0],&pixel[1],&pixel[2]); /* FIXME: Actually needs uyvy? */ + pixel[3] = 255; + } + } + return converted_data; } else { return data; } @@ -1974,10 +2007,18 @@ static TextureBinding* generate_texture(const TextureShape s, glPixelStorei(GL_UNPACK_ROW_LENGTH, s.pitch / f.bytes_per_pixel); + uint8_t *converted = convert_texture_data(s, texture_data, + palette_data, + s.width, s.height, s.pitch); + glTexImage2D(gl_target, 0, f.gl_internal_format, s.width, s.height, 0, f.gl_format, f.gl_type, - texture_data); + converted); + + if (converted != texture_data) { + g_free(converted); + } glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { @@ -2020,22 +2061,6 @@ static TextureBinding* generate_texture(const TextureShape s, palette_data, width, height, pitch); - if (s.color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8) { - data = g_malloc(height * pitch * 4); - unsigned int y; - for(y = 0; y < height; y++) { - unsigned int x; - for(x = 0; x < pitch; x++) { - uint8_t* pixel = &data[(y * pitch + x) * 4]; - //FIXME: Steal format conversion from video stuff above - pixel[0] = 255; - pixel[1] = 0; - pixel[2] = 255; - pixel[3] = 128; - } - } - } - glTexImage2D(gl_target, level, f.gl_internal_format, width, height, 0, f.gl_format, f.gl_type, @@ -6090,11 +6115,6 @@ static void pgraph_method_log(unsigned int subchannel, last = method; } -static uint8_t cliptobyte(int x) -{ - return (uint8_t)((x < 0) ? 0 : ((x > 255) ? 255 : x)); -} - static void nv2a_overlay_draw_line(VGACommonState *vga, uint8_t *line, int y) { NV2A_DPRINTF("nv2a_overlay_draw_line\n"); @@ -6155,19 +6175,8 @@ static void nv2a_overlay_draw_line(VGACommonState *vga, uint8_t *line, int y) if (ix >= in_width) break; // YUY2 to RGB - int c, d, e; - c = (int)in_line[ix * 2] - 16; - if (ix % 2) { - d = (int)in_line[ix * 2 - 1] - 128; - e = (int)in_line[ix * 2 + 1] - 128; - } else { - d = (int)in_line[ix * 2 + 1] - 128; - e = (int)in_line[ix * 2 + 3] - 128; - } - int r, g, b; - r = cliptobyte((298 * c + 409 * e + 128) >> 8); - g = cliptobyte((298 * c - 100 * d - 208 * e + 128) >> 8); - b = cliptobyte((298 * c + 516 * d + 128) >> 8); + uint8_t r,g,b; + convert_yuy2_to_rgb(in_line,ix,&r,&g,&b); unsigned int pixel = vga->rgb_to_pixel(r, g, b); switch (surf_bpp) { From 2e0a16873d853141b4e7d3a6ce7bd8223974a044 Mon Sep 17 00:00:00 2001 From: Jannik Vogel <email@jannikvogel.de> Date: Mon, 13 Jul 2015 18:21:43 +0200 Subject: [PATCH 7/8] Cleanup uyvy --- hw/xbox/nv2a.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 5b63c17fa7..29f364dcc1 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -1955,14 +1955,16 @@ static uint8_t* convert_texture_data(const TextureShape s, } } return converted_data; - } else if (s.color_format == NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8) { + } else if (s.color_format + == NV097_SET_TEXTURE_FORMAT_COLOR_LC_IMAGE_CR8YB8CB8YA8) { uint8_t* converted_data = g_malloc(width * height * 4); int x, y; for (y = 0; y < height; y++) { uint8_t* line = &data[y * s.width * 2]; for (x = 0; x < width; x++) { uint8_t* pixel = &converted_data[(y * s.width + x) * 4]; - convert_yuy2_to_rgb(line,x,&pixel[0],&pixel[1],&pixel[2]); /* FIXME: Actually needs uyvy? */ + /* FIXME: Actually needs uyvy? */ + convert_yuy2_to_rgb(line,x,&pixel[0],&pixel[1],&pixel[2]); pixel[3] = 255; } } From ec7a83d745a10263169fab27cf2b8672a2d00745 Mon Sep 17 00:00:00 2001 From: espes <espes@pequalsnp.com> Date: Tue, 14 Jul 2015 02:52:59 +1000 Subject: [PATCH 8/8] some style and const-correctness fixes --- hw/xbox/nv2a.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/hw/xbox/nv2a.c b/hw/xbox/nv2a.c index 29f364dcc1..9b2d4987d1 100644 --- a/hw/xbox/nv2a.c +++ b/hw/xbox/nv2a.c @@ -1922,7 +1922,8 @@ static uint8_t cliptobyte(int x) return (uint8_t)((x < 0) ? 0 : ((x > 255) ? 255 : x)); } -static void convert_yuy2_to_rgb(uint8_t* line, unsigned int ix, uint8_t* r, uint8_t* g, uint8_t* b) { +static void convert_yuy2_to_rgb(const uint8_t *line, unsigned int ix, + uint8_t *r, uint8_t *g, uint8_t* b) { int c, d, e; c = (int)line[ix * 2] - 16; if (ix % 2) { @@ -1932,14 +1933,13 @@ static void convert_yuy2_to_rgb(uint8_t* line, unsigned int ix, uint8_t* r, uint d = (int)line[ix * 2 + 1] - 128; e = (int)line[ix * 2 + 3] - 128; } - if (r) { *r = cliptobyte((298 * c + 409 * e + 128) >> 8); } - if (g) { *g = cliptobyte((298 * c - 100 * d - 208 * e + 128) >> 8); } - if (b) { *b = cliptobyte((298 * c + 516 * d + 128) >> 8); } - return; + *r = cliptobyte((298 * c + 409 * e + 128) >> 8); + *g = cliptobyte((298 * c - 100 * d - 208 * e + 128) >> 8); + *b = cliptobyte((298 * c + 516 * d + 128) >> 8); } static uint8_t* convert_texture_data(const TextureShape s, - uint8_t *data, + const uint8_t *data, const uint8_t *palette_data, unsigned int width, unsigned int height, unsigned int pitch) @@ -1960,17 +1960,17 @@ static uint8_t* convert_texture_data(const TextureShape s, uint8_t* converted_data = g_malloc(width * height * 4); int x, y; for (y = 0; y < height; y++) { - uint8_t* line = &data[y * s.width * 2]; + const uint8_t* line = &data[y * s.width * 2]; for (x = 0; x < width; x++) { uint8_t* pixel = &converted_data[(y * s.width + x) * 4]; /* FIXME: Actually needs uyvy? */ - convert_yuy2_to_rgb(line,x,&pixel[0],&pixel[1],&pixel[2]); + convert_yuy2_to_rgb(line, x, &pixel[0], &pixel[1], &pixel[2]); pixel[3] = 255; } } return converted_data; } else { - return data; + return NULL; } } @@ -2016,9 +2016,9 @@ static TextureBinding* generate_texture(const TextureShape s, glTexImage2D(gl_target, 0, f.gl_internal_format, s.width, s.height, 0, f.gl_format, f.gl_type, - converted); + converted ? converted : texture_data); - if (converted != texture_data) { + if (converted) { g_free(converted); } @@ -2066,9 +2066,9 @@ static TextureBinding* generate_texture(const TextureShape s, glTexImage2D(gl_target, level, f.gl_internal_format, width, height, 0, f.gl_format, f.gl_type, - converted); + converted ? converted : unswizzled); - if (converted != unswizzled) { + if (converted) { g_free(converted); } g_free(unswizzled); @@ -6176,9 +6176,8 @@ static void nv2a_overlay_draw_line(VGACommonState *vga, uint8_t *line, int y) int ix = in_s + x; if (ix >= in_width) break; - // YUY2 to RGB uint8_t r,g,b; - convert_yuy2_to_rgb(in_line,ix,&r,&g,&b); + convert_yuy2_to_rgb(in_line, ix, &r, &g, &b); unsigned int pixel = vga->rgb_to_pixel(r, g, b); switch (surf_bpp) {