From d145e78cd6a8fca8fa63d5569310433a8d0c3c40 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sat, 8 Nov 2025 10:22:15 -0800 Subject: [PATCH] Improved performance scaling 8-bit surfaces --- src/video/SDL_pixels.c | 29 ++++++++++++++++++----------- src/video/SDL_pixels_c.h | 1 + src/video/SDL_surface.c | 8 +++++++- 3 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 612340b464..70ea85b570 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -1441,24 +1441,31 @@ void SDL_GetRGBA(Uint32 pixelvalue, const SDL_PixelFormatDetails *format, const } } +bool SDL_IsSamePalette(const SDL_Palette *src, const SDL_Palette *dst) +{ + if (src->ncolors <= dst->ncolors) { + // If an identical palette, no need to map + if (src == dst || + (SDL_memcmp(src->colors, dst->colors, + src->ncolors * sizeof(SDL_Color)) == 0)) { + return true; + } + } + return false; +} + // Map from Palette to Palette static Uint8 *Map1to1(const SDL_Palette *src, const SDL_Palette *dst, int *identical) { Uint8 *map; int i; - if (identical) { - if (src->ncolors <= dst->ncolors) { - // If an identical palette, no need to map - if (src == dst || - (SDL_memcmp(src->colors, dst->colors, - src->ncolors * sizeof(SDL_Color)) == 0)) { - *identical = 1; - return NULL; - } - } - *identical = 0; + if (SDL_IsSamePalette(src, dst)) { + *identical = 1; + return NULL; } + *identical = 0; + map = (Uint8 *)SDL_calloc(256, sizeof(Uint8)); if (!map) { return NULL; diff --git a/src/video/SDL_pixels_c.h b/src/video/SDL_pixels_c.h index f6411f7cbd..91d102a26f 100644 --- a/src/video/SDL_pixels_c.h +++ b/src/video/SDL_pixels_c.h @@ -48,6 +48,7 @@ extern void SDL_InvalidateMap(SDL_BlitMap *map); extern bool SDL_MapSurface(SDL_Surface *src, SDL_Surface *dst); // Miscellaneous functions +extern bool SDL_IsSamePalette(const SDL_Palette *src, const SDL_Palette *dst); extern void SDL_DitherPalette(SDL_Palette *palette); extern Uint8 SDL_FindColor(const SDL_Palette *pal, Uint8 r, Uint8 g, Uint8 b, Uint8 a); extern Uint8 SDL_LookupRGBAColor(SDL_HashTable *palette_map, Uint32 pixelvalue, const SDL_Palette *pal); diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index d5936e1aba..d3c18d4060 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -1252,7 +1252,8 @@ bool SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, S if (scaleMode == SDL_SCALEMODE_NEAREST || scaleMode == SDL_SCALEMODE_PIXELART) { if (!(src->map.info.flags & complex_copy_flags) && src->format == dst->format && - !SDL_ISPIXELFORMAT_INDEXED(src->format) && + (!SDL_ISPIXELFORMAT_INDEXED(src->format) || + (SDL_BITSPERPIXEL(src->format) == 8 && SDL_IsSamePalette(src->palette, dst->palette))) && SDL_BYTESPERPIXEL(src->format) <= 4) { return SDL_StretchSurface(src, srcrect, dst, dstrect, SDL_SCALEMODE_NEAREST); } else if (SDL_BITSPERPIXEL(src->format) < 8) { @@ -2244,6 +2245,11 @@ SDL_Surface *SDL_ScaleSurface(SDL_Surface *surface, int width, int height, SDL_S return result; } + if (SDL_ISPIXELFORMAT_INDEXED(surface->format)) { + // Linear scaling requires conversion to RGBA and then slow pixel color lookup + scaleMode = SDL_SCALEMODE_NEAREST; + } + // Create a new surface with the desired size if (surface->pixels || SDL_MUSTLOCK(surface)) { convert = SDL_CreateSurface(width, height, surface->format);