From d145e78cd6a8fca8fa63d5569310433a8d0c3c40 Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
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 612340b464532..70ea85b57070a 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 f6411f7cbdb10..91d102a26fe42 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 d5936e1aba661..d3c18d40605f8 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);