Copy the palette instead of referencing it when creating a texture
Build (All) / Create test plan (push) Has been cancelled
Build (All) / level1 (push) Has been cancelled
Build (All) / level2 (push) Has been cancelled

Fixes https://github.com/libsdl-org/SDL/issues/14213
This commit is contained in:
Sam Lantinga
2025-10-11 10:44:38 -07:00
parent 2c63bc7315
commit 480f069cec
+33 -23
View File
@@ -1686,7 +1686,6 @@ static bool SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, S
bool direct_update; bool direct_update;
if (surface->format == texture->format && if (surface->format == texture->format &&
surface->palette == texture->public_palette &&
SDL_GetSurfaceColorspace(surface) == texture->colorspace) { SDL_GetSurfaceColorspace(surface) == texture->colorspace) {
if (SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) { if (SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
/* Surface and Renderer formats are identical. /* Surface and Renderer formats are identical.
@@ -1721,6 +1720,21 @@ static bool SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, S
} }
} }
if (texture->format == surface->format && surface->palette) {
// Copy the palette to the new texture
SDL_Palette *existing = surface->palette;
SDL_Palette *palette = SDL_CreatePalette(existing->ncolors);
if (palette &&
SDL_SetPaletteColors(palette, existing->colors, 0, existing->ncolors) &&
SDL_SetTexturePalette(texture, palette)) {
// The texture has a reference to the palette now
SDL_DestroyPalette(palette);
} else {
SDL_DestroyPalette(palette);
return false;
}
}
{ {
Uint8 r, g, b, a; Uint8 r, g, b, a;
SDL_BlendMode blendMode; SDL_BlendMode blendMode;
@@ -1745,10 +1759,8 @@ static bool SDL_UpdateTextureFromSurface(SDL_Texture *texture, SDL_Rect *rect, S
SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface) SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *surface)
{ {
bool needAlpha;
int i; int i;
SDL_PixelFormat format = SDL_PIXELFORMAT_UNKNOWN; SDL_PixelFormat format = SDL_PIXELFORMAT_UNKNOWN;
SDL_Palette *palette;
SDL_Texture *texture; SDL_Texture *texture;
SDL_PropertiesID props; SDL_PropertiesID props;
SDL_Colorspace surface_colorspace = SDL_COLORSPACE_UNKNOWN; SDL_Colorspace surface_colorspace = SDL_COLORSPACE_UNKNOWN;
@@ -1761,23 +1773,6 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
return NULL; return NULL;
} }
// See what the best texture format is
if (SDL_ISPIXELFORMAT_ALPHA(surface->format) || SDL_SurfaceHasColorKey(surface)) {
needAlpha = true;
} else {
needAlpha = false;
}
// If palette contains alpha values, promotes to alpha format
palette = SDL_GetSurfacePalette(surface);
if (palette) {
bool is_opaque, has_alpha_channel;
SDL_DetectPalette(palette, &is_opaque, &has_alpha_channel);
if (!is_opaque) {
needAlpha = true;
}
}
// Try to have the best pixel format for the texture // Try to have the best pixel format for the texture
// No alpha, but a colorkey => promote to alpha // No alpha, but a colorkey => promote to alpha
if (!SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) { if (!SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) {
@@ -1830,6 +1825,24 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
// Fallback, choose a valid pixel format // Fallback, choose a valid pixel format
if (format == SDL_PIXELFORMAT_UNKNOWN) { if (format == SDL_PIXELFORMAT_UNKNOWN) {
format = renderer->texture_formats[0]; format = renderer->texture_formats[0];
// See what the best texture format is
bool needAlpha;
if (SDL_ISPIXELFORMAT_ALPHA(surface->format) || SDL_SurfaceHasColorKey(surface)) {
needAlpha = true;
} else {
needAlpha = false;
}
// If palette contains alpha values, promotes to alpha format
if (surface->palette) {
bool is_opaque, has_alpha_channel;
SDL_DetectPalette(surface->palette, &is_opaque, &has_alpha_channel);
if (!is_opaque) {
needAlpha = true;
}
}
for (i = 0; i < renderer->num_texture_formats; ++i) { for (i = 0; i < renderer->num_texture_formats; ++i) {
if (!SDL_ISPIXELFORMAT_FOURCC(renderer->texture_formats[i]) && if (!SDL_ISPIXELFORMAT_FOURCC(renderer->texture_formats[i]) &&
SDL_ISPIXELFORMAT_ALPHA(renderer->texture_formats[i]) == needAlpha) { SDL_ISPIXELFORMAT_ALPHA(renderer->texture_formats[i]) == needAlpha) {
@@ -1865,9 +1878,6 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_ACCESS_NUMBER, SDL_TEXTUREACCESS_STATIC);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, surface->w); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_WIDTH_NUMBER, surface->w);
SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, surface->h); SDL_SetNumberProperty(props, SDL_PROP_TEXTURE_CREATE_HEIGHT_NUMBER, surface->h);
if (format == surface->format && palette) {
SDL_SetPointerProperty(props, SDL_PROP_TEXTURE_CREATE_PALETTE_POINTER, palette);
}
texture = SDL_CreateTextureWithProperties(renderer, props); texture = SDL_CreateTextureWithProperties(renderer, props);
SDL_DestroyProperties(props); SDL_DestroyProperties(props);
if (!texture) { if (!texture) {