From 838bbf1f7a3c5a18a523fa6967222cac732767e9 Mon Sep 17 00:00:00 2001 From: Sylvain Becker Date: Tue, 17 Mar 2020 09:35:42 +0100 Subject: [PATCH] Fixed bug 5037 - Regression 2.0.12 Alpha value of 0 on palette may become opaque (see also bug 3827) --- src/render/SDL_render.c | 10 ++++----- src/video/SDL_pixels.c | 48 ++++++++++++++++++++++++++++++++++++++++ src/video/SDL_pixels_c.h | 1 + src/video/SDL_surface.c | 20 ++++++----------- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 59c2f4992cb3d..dfa70bc63021c 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1165,12 +1165,10 @@ SDL_CreateTextureFromSurface(SDL_Renderer * renderer, SDL_Surface * surface) /* If Palette contains alpha values, promotes to alpha format */ if (fmt->palette) { - for (i = 0; i < fmt->palette->ncolors; i++) { - Uint8 alpha_value = fmt->palette->colors[i].a; - if (alpha_value != 0 && alpha_value != SDL_ALPHA_OPAQUE) { - needAlpha = SDL_TRUE; - break; - } + SDL_bool is_opaque, has_alpha_channel; + SDL_DetectPalette(fmt->palette, &is_opaque, &has_alpha_channel); + if (!is_opaque) { + needAlpha = SDL_TRUE; } } diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index f02a2bd21cd33..77de36c51d29d 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -801,6 +801,54 @@ SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a) return (pixel); } +/* Tell whether palette is opaque, and if it has an alpha_channel */ +void +SDL_DetectPalette(SDL_Palette *pal, SDL_bool *is_opaque, SDL_bool *has_alpha_channel) +{ + int i; + + { + SDL_bool all_opaque = SDL_TRUE; + for (i = 0; i < pal->ncolors; i++) { + Uint8 alpha_value = pal->colors[i].a; + if (alpha_value != SDL_ALPHA_OPAQUE) { + all_opaque = SDL_FALSE; + break; + } + } + + if (all_opaque) { + /* Palette is opaque, with an alpha channel */ + *is_opaque = SDL_TRUE; + *has_alpha_channel = SDL_TRUE; + return; + } + } + + { + SDL_bool all_transparent = SDL_TRUE; + for (i = 0; i < pal->ncolors; i++) { + Uint8 alpha_value = pal->colors[i].a; + if (alpha_value != SDL_ALPHA_TRANSPARENT) { + all_transparent = SDL_FALSE; + break; + } + } + + if (all_transparent) { + /* Palette is opaque, without an alpha channel */ + *is_opaque = SDL_TRUE; + *has_alpha_channel = SDL_FALSE; + return; + } + } + + /* Palette has alpha values */ + *is_opaque = SDL_FALSE; + *has_alpha_channel = SDL_TRUE; +} + + /* Find the opaque pixel value corresponding to an RGB triple */ Uint32 SDL_MapRGB(const SDL_PixelFormat * format, Uint8 r, Uint8 g, Uint8 b) diff --git a/src/video/SDL_pixels_c.h b/src/video/SDL_pixels_c.h index c4baf41b9959f..8f511c0d2e8b7 100644 --- a/src/video/SDL_pixels_c.h +++ b/src/video/SDL_pixels_c.h @@ -40,6 +40,7 @@ extern void SDL_FreeBlitMap(SDL_BlitMap * map); /* Miscellaneous functions */ extern void SDL_DitherColors(SDL_Color * colors, int bpp); extern Uint8 SDL_FindColor(SDL_Palette * pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a); +extern void SDL_DetectPalette(SDL_Palette *pal, SDL_bool *is_opaque, SDL_bool *has_alpha_channel); #endif /* SDL_pixels_c_h_ */ diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 3795b94d37e59..77a6bc84ac206 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -1032,22 +1032,16 @@ SDL_ConvertSurface(SDL_Surface * surface, const SDL_PixelFormat * format, * -> set alpha channel to be opaque */ if (surface->format->palette && format->Amask) { SDL_bool set_opaque = SDL_FALSE; - { - int i; - for (i = 0; i < surface->format->palette->ncolors; i++) { - Uint8 alpha_value = surface->format->palette->colors[i].a; - if (alpha_value != 0 && alpha_value != SDL_ALPHA_OPAQUE) { - /* Palette has at least one alpha value. Don't do anything */ - set_opaque = SDL_FALSE; - palette_has_alpha = SDL_TRUE; - break; - } + SDL_bool is_opaque, has_alpha_channel; + SDL_DetectPalette(surface->format->palette, &is_opaque, &has_alpha_channel); - if (alpha_value == 0) { - set_opaque = SDL_TRUE; - } + if (is_opaque) { + if (!has_alpha_channel) { + set_opaque = SDL_TRUE; } + } else { + palette_has_alpha = SDL_TRUE; } /* Set opaque and backup palette alpha values */