From c0a2ae2a4a9826a15df347ad9be61436090bbf8f Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 23 Nov 2025 11:38:35 -0800 Subject: [PATCH] opengles2: fixed swapped colors when using indexed textures --- src/render/opengles2/SDL_render_gles2.c | 19 +++++- src/render/opengles2/SDL_shaders_gles2.c | 82 +++++++++++++++++------- src/render/opengles2/SDL_shaders_gles2.h | 3 + 3 files changed, 79 insertions(+), 25 deletions(-) diff --git a/src/render/opengles2/SDL_render_gles2.c b/src/render/opengles2/SDL_render_gles2.c index 2d2d725cb1..74644e7de5 100644 --- a/src/render/opengles2/SDL_render_gles2.c +++ b/src/render/opengles2/SDL_render_gles2.c @@ -628,6 +628,7 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL GLES2_ShaderType vtype, ftype; GLES2_ProgramCacheEntry *program; GLES2_TextureData *tdata = texture ? (GLES2_TextureData *)texture->internal : NULL; + const bool colorswap = (data->drawstate.target && (data->drawstate.target->format == SDL_PIXELFORMAT_BGRA32 || data->drawstate.target->format == SDL_PIXELFORMAT_BGRX32)); const float *shader_params = NULL; int shader_params_len = 0; @@ -640,15 +641,27 @@ static bool GLES2_SelectProgram(GLES2_RenderData *data, SDL_Texture *texture, GL case GLES2_IMAGESOURCE_TEXTURE_INDEX8: switch (scale_mode) { case SDL_SCALEMODE_NEAREST: - ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_NEAREST; + if (colorswap) { + ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_NEAREST_COLORSWAP; + } else { + ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_NEAREST; + } break; case SDL_SCALEMODE_LINEAR: - ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR; + if (colorswap) { + ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR_COLORSWAP; + } else { + ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR; + } shader_params = tdata->texel_size; shader_params_len = 4 * sizeof(float); break; case SDL_SCALEMODE_PIXELART: - ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART; + if (colorswap) { + ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART_COLORSWAP; + } else { + ftype = GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART; + } shader_params = tdata->texel_size; shader_params_len = 4 * sizeof(float); break; diff --git a/src/render/opengles2/SDL_shaders_gles2.c b/src/render/opengles2/SDL_shaders_gles2.c index 6b109227a0..76786026ff 100644 --- a/src/render/opengles2/SDL_shaders_gles2.c +++ b/src/render/opengles2/SDL_shaders_gles2.c @@ -167,7 +167,20 @@ static const char GLES2_Fragment_TexturePalette_Nearest[] = "\n" "void main()\n" "{\n" -" gl_FragColor = SamplePaletteNearest(v_texCoord);\n" +" mediump vec4 color = SamplePaletteNearest(v_texCoord);\n" +" gl_FragColor = color;\n" +" gl_FragColor *= v_color;\n" +"}\n" +; + +static const char GLES2_Fragment_TexturePalette_Nearest_Colorswap[] = + PALETTE_SHADER_PROLOGUE + PALETTE_SHADER_FUNCTIONS +"\n" +"void main()\n" +"{\n" +" mediump vec4 color = SamplePaletteNearest(v_texCoord);\n" +" gl_FragColor = vec4(color.b, color.g, color.r, color.a);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -178,7 +191,20 @@ static const char GLES2_Fragment_TexturePalette_Linear[] = "\n" "void main()\n" "{\n" -" gl_FragColor = SamplePaletteLinear(v_texCoord);\n" +" mediump vec4 color = SamplePaletteLinear(v_texCoord);\n" +" gl_FragColor = color;\n" +" gl_FragColor *= v_color;\n" +"}\n" +; + +static const char GLES2_Fragment_TexturePalette_Linear_Colorswap[] = + PALETTE_SHADER_PROLOGUE + PALETTE_SHADER_FUNCTIONS +"\n" +"void main()\n" +"{\n" +" mediump vec4 color = SamplePaletteLinear(v_texCoord);\n" +" gl_FragColor = vec4(color.b, color.g, color.r, color.a);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -191,10 +217,28 @@ static const char GLES2_Fragment_TexturePalette_PixelArt[] = "void main()\n" "{\n" #ifdef OPENGLES_300 -" gl_FragColor = SamplePaletteLinear(GetPixelArtUV(v_texCoord));\n" +" mediump vec4 color = SamplePaletteLinear(GetPixelArtUV(v_texCoord));\n" #else -" gl_FragColor = SamplePaletteNearest(v_texCoord);\n" +" mediump vec4 color = SamplePaletteNearest(v_texCoord);\n" #endif +" gl_FragColor = color;\n" +" gl_FragColor *= v_color;\n" +"}\n" +; + +static const char GLES2_Fragment_TexturePalette_PixelArt_Colorswap[] = + PALETTE_SHADER_PROLOGUE + PALETTE_SHADER_FUNCTIONS + PIXELART_SHADER_FUNCTIONS +"\n" +"void main()\n" +"{\n" +#ifdef OPENGLES_300 +" mediump vec4 color = SamplePaletteLinear(GetPixelArtUV(v_texCoord));\n" +#else +" mediump vec4 color = SamplePaletteNearest(v_texCoord);\n" +#endif +" gl_FragColor = vec4(color.b, color.g, color.r, color.a);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -206,10 +250,7 @@ static const char GLES2_Fragment_TextureRGB[] = "void main()\n" "{\n" " mediump vec4 color = texture2D(u_texture, v_texCoord);\n" -" gl_FragColor = color;\n" -" gl_FragColor.r = color.b;\n" -" gl_FragColor.b = color.r;\n" -" gl_FragColor.a = 1.0;\n" +" gl_FragColor = vec4(color.b, color.g, color.r, 1.0);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -222,10 +263,7 @@ static const char GLES2_Fragment_TextureRGB_PixelArt[] = "void main()\n" "{\n" " mediump vec4 color = GetPixelArtSample(v_texCoord);\n" -" gl_FragColor = color;\n" -" gl_FragColor.r = color.b;\n" -" gl_FragColor.b = color.r;\n" -" gl_FragColor.a = 1.0;\n" +" gl_FragColor = vec4(color.b, color.g, color.r, 1.0);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -237,8 +275,7 @@ static const char GLES2_Fragment_TextureBGR[] = "void main()\n" "{\n" " mediump vec4 color = texture2D(u_texture, v_texCoord);\n" -" gl_FragColor = color;\n" -" gl_FragColor.a = 1.0;\n" +" gl_FragColor = vec4(color.r, color.g, color.b, 1.0);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -251,8 +288,7 @@ static const char GLES2_Fragment_TextureBGR_PixelArt[] = "void main()\n" "{\n" " mediump vec4 color = GetPixelArtSample(v_texCoord);\n" -" gl_FragColor = color;\n" -" gl_FragColor.a = 1.0;\n" +" gl_FragColor = vec4(color.r, color.g, color.b, 1.0);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -264,9 +300,7 @@ static const char GLES2_Fragment_TextureARGB[] = "void main()\n" "{\n" " mediump vec4 color = texture2D(u_texture, v_texCoord);\n" -" gl_FragColor = color;\n" -" gl_FragColor.r = color.b;\n" -" gl_FragColor.b = color.r;\n" +" gl_FragColor = vec4(color.b, color.g, color.r, color.a);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -279,9 +313,7 @@ static const char GLES2_Fragment_TextureARGB_PixelArt[] = "void main()\n" "{\n" " mediump vec4 color = GetPixelArtSample(v_texCoord);\n" -" gl_FragColor = color;\n" -" gl_FragColor.r = color.b;\n" -" gl_FragColor.b = color.r;\n" +" gl_FragColor = vec4(color.b, color.g, color.r, color.a);\n" " gl_FragColor *= v_color;\n" "}\n" ; @@ -524,6 +556,12 @@ const char *GLES2_GetShader(GLES2_ShaderType type) return GLES2_Fragment_TexturePalette_Linear; case GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART: return GLES2_Fragment_TexturePalette_PixelArt; + case GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_NEAREST_COLORSWAP: + return GLES2_Fragment_TexturePalette_Nearest_Colorswap; + case GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR_COLORSWAP: + return GLES2_Fragment_TexturePalette_Linear_Colorswap; + case GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART_COLORSWAP: + return GLES2_Fragment_TexturePalette_PixelArt_Colorswap; case GLES2_SHADER_FRAGMENT_TEXTURE_RGB: return GLES2_Fragment_TextureRGB; case GLES2_SHADER_FRAGMENT_TEXTURE_RGB_PIXELART: diff --git a/src/render/opengles2/SDL_shaders_gles2.h b/src/render/opengles2/SDL_shaders_gles2.h index c29ced6994..a0a40a0879 100644 --- a/src/render/opengles2/SDL_shaders_gles2.h +++ b/src/render/opengles2/SDL_shaders_gles2.h @@ -42,6 +42,9 @@ typedef enum GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_NEAREST, GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR, GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART, + GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_NEAREST_COLORSWAP, + GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_LINEAR_COLORSWAP, + GLES2_SHADER_FRAGMENT_TEXTURE_PALETTE_PIXELART_COLORSWAP, GLES2_SHADER_FRAGMENT_TEXTURE_RGB, GLES2_SHADER_FRAGMENT_TEXTURE_RGB_PIXELART, GLES2_SHADER_FRAGMENT_TEXTURE_BGR,