From 12d9d6bdd2c10fce3d6a3bdc6e401b22e5cc1e88 Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Fri, 17 May 2024 23:20:34 +0300 Subject: [PATCH] Add pure luminance and alpha textures There should be a difference between these two, but for now we lack a test case. At the moment they both act as alpha textures. --- src/gc_gl.c | 21 ++++++++++++++++++--- src/pixels.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ src/pixels.h | 3 +++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/src/gc_gl.c b/src/gc_gl.c index 000c4af..26d530d 100644 --- a/src/gc_gl.c +++ b/src/gc_gl.c @@ -1458,6 +1458,14 @@ void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei widt } else if (internalFormat == GL_LUMINANCE_ALPHA) { bytesperpixelinternal = 2; gx_format = GX_TF_IA8; + } else if (internalFormat == GL_LUMINANCE) { + bytesperpixelinternal = 1; + gx_format = GX_TF_I8; + } else if (internalFormat == GL_ALPHA) { + bytesperpixelinternal = 1; + /* GX_TF_A8 is not supported by Dolphin and if not properly handed by a + * real Wii either. */ + gx_format = GX_TF_I8; } else { gx_format = GX_TF_CMPR; } @@ -1534,7 +1542,9 @@ void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei widt // Inconditionally convert to 565 all inputs without alpha channel // Alpha inputs may be stripped if the user specifies an alpha-free internal format if (bytesperpixelinternal > 0) { - unsigned char *tempbuf = malloc(width * height * bytesperpixelinternal); + /* Add pixels on each direction so that the scrambling functions can + * read whole 4x4 (or 8x4) tiles without bound checking */ + unsigned char *tempbuf = malloc((width + 7) * (height + 3) * bytesperpixelinternal); if (!tempbuf) { warning("Failed to allocate memory for texture (%d)", errno); set_error(GL_OUT_OF_MEMORY); @@ -1557,10 +1567,13 @@ void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei widt } else if (internalFormat == GL_LUMINANCE_ALPHA) { _ogx_conv_luminance_alpha_to_ia8(data, type, tempbuf, width, height); } + } else if (format == GL_ALPHA || format == GL_LUMINANCE) { + _ogx_conv_intensity_to_i8(data, type, tempbuf, width, height); } // Swap R<->B if necessary - if (needswap && internalFormat != GL_LUMINANCE_ALPHA) { + if (needswap && bytesperpixelinternal > 1 && + internalFormat != GL_LUMINANCE_ALPHA) { if (bytesperpixelinternal == 4) _ogx_swap_rgba(tempbuf, width * height); else @@ -1575,8 +1588,10 @@ void glTexImage2D(GLenum target, GLint level, GLint internalFormat, GLsizei widt // Finally write to the dest. buffer scrambling the data if (bytesperpixelinternal == 4) { _ogx_scramble_4b(tempbuf, dst_addr, width, height); - } else { + } else if (bytesperpixelinternal == 2) { _ogx_scramble_2b((unsigned short *)tempbuf, dst_addr, width, height); + } else if (bytesperpixelinternal == 1) { + _ogx_scramble_1b(tempbuf, dst_addr, width, height); } free(tempbuf); diff --git a/src/pixels.c b/src/pixels.c index 22a5b9d..90e9d1f 100644 --- a/src/pixels.c +++ b/src/pixels.c @@ -35,6 +35,7 @@ POSSIBILITY OF SUCH DAMAGE. #include "debug.h" #include #include +#include #define FLOAT_TO_BYTE(f) ((GLbyte)(f * 255.0) & 0xff) @@ -164,6 +165,32 @@ void _ogx_conv_rgba_to_rgba32(const void *data, GLenum type, } } +static void conv_intensityf_to_i8(const float *src, void *dst, int numpixels) +{ + uint32_t *out = dst; + while (numpixels--) { + *out++ = FLOAT_TO_BYTE(src[0]); + src++; + } +} + +void _ogx_conv_intensity_to_i8(const void *data, GLenum type, + void *dest, int width, int height) +{ + int numpixels = width * height; + switch (type) { + case GL_BYTE: + case GL_UNSIGNED_BYTE: + memcpy(dest, data, numpixels); + break; + case GL_FLOAT: + conv_intensityf_to_i8(data, dest, numpixels); + break; + default: + warning("Unsupported texture format %d", type); + } +} + static void conv_laf_to_ia8(const float *src, void *dst, int numpixels) { uint16_t *out = dst; @@ -206,6 +233,23 @@ void _ogx_conv_rgba_to_luminance_alpha(unsigned char *src, void *dst, } // 4x4 tile scrambling +/* 1b texel scrambling */ +void _ogx_scramble_1b(void *src, void *dst, int width, int height) +{ + uint64_t *s = src; + uint64_t *p = dst; + + int width_blocks = (width + 7) / 8; + for (int y = 0; y < height; y += 4) { + int rows = MIN(height - y, 4); + for (int x = 0; x < width_blocks; x++) { + for (int row = 0; row < rows; row++) { + *p++ = s[(y + row) * width_blocks + x]; + } + } + } +} + // 2b texel scrambling void _ogx_scramble_2b(unsigned short *src, void *dst, const unsigned int width, const unsigned int height) diff --git a/src/pixels.h b/src/pixels.h index 716107c..c09b00f 100644 --- a/src/pixels.h +++ b/src/pixels.h @@ -47,6 +47,9 @@ void _ogx_conv_luminance_alpha_to_ia8(const void *data, GLenum type, void *dest, int width, int height); void _ogx_conv_rgba_to_luminance_alpha(unsigned char *src, void *dst, const unsigned int width, const unsigned int height); +void _ogx_conv_intensity_to_i8(const void *data, GLenum type, + void *dest, int width, int height); +void _ogx_scramble_1b(void *src, void *dst, int width, int height); void _ogx_scramble_2b(unsigned short *src, void *dst, const unsigned int width, const unsigned int height); void _ogx_scramble_4b(unsigned char *src, void *dst,