From 8677198b1e9a518e9c300c7a158fae4e33a627d1 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Wed, 13 May 2026 18:32:51 +0100 Subject: [PATCH 1/2] Detect the best pixel format for intermediate scaled surfaces. --- src/render/SDL_render.c | 26 ++----- src/render/software/SDL_render_sw.c | 115 ++++++---------------------- src/render/software/SDL_triangle.c | 10 ++- src/video/SDL_pixels.c | 77 +++++++++++++++++++ src/video/SDL_pixels_c.h | 2 + src/video/SDL_rotate.c | 4 +- src/video/SDL_stretch.c | 3 +- src/video/SDL_surface.c | 21 ++--- src/video/SDL_yuv.c | 12 +-- 9 files changed, 133 insertions(+), 137 deletions(-) diff --git a/src/render/SDL_render.c b/src/render/SDL_render.c index 9894d44678..60068587d2 100644 --- a/src/render/SDL_render.c +++ b/src/render/SDL_render.c @@ -1790,24 +1790,11 @@ SDL_Texture *SDL_CreateTextureFromSurface(SDL_Renderer *renderer, SDL_Surface *s // Try to have the best pixel format for the texture // No alpha, but a colorkey => promote to alpha if (!SDL_ISPIXELFORMAT_ALPHA(surface->format) && SDL_SurfaceHasColorKey(surface)) { - if (surface->format == SDL_PIXELFORMAT_XRGB8888) { + SDL_PixelFormat alphafmt = SDL_PromotePixelFormatToAlpha(surface->format); + if (alphafmt != SDL_PIXELFORMAT_UNKNOWN) { for (i = 0; i < renderer->num_texture_formats; ++i) { - if (renderer->texture_formats[i] == SDL_PIXELFORMAT_ARGB8888) { - format = SDL_PIXELFORMAT_ARGB8888; - break; - } - } - } else if (surface->format == SDL_PIXELFORMAT_XBGR8888) { - for (i = 0; i < renderer->num_texture_formats; ++i) { - if (renderer->texture_formats[i] == SDL_PIXELFORMAT_ABGR8888) { - format = SDL_PIXELFORMAT_ABGR8888; - break; - } - } - } else if (surface->format == SDL_PIXELFORMAT_XRGB4444) { - for (i = 0; i < renderer->num_texture_formats; ++i) { - if (renderer->texture_formats[i] == SDL_PIXELFORMAT_ARGB4444) { - format = SDL_PIXELFORMAT_ARGB4444; + if (renderer->texture_formats[i] == alphafmt) { + format = alphafmt; break; } } @@ -5461,10 +5448,7 @@ SDL_Surface *SDL_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect *rect) SDL_SetFloatProperty(props, SDL_PROP_SURFACE_HDR_HEADROOM_FLOAT, target->HDR_headroom); // Set the expected surface format - if ((surface->format == SDL_PIXELFORMAT_ARGB8888 && expected_format == SDL_PIXELFORMAT_XRGB8888) || - (surface->format == SDL_PIXELFORMAT_RGBA8888 && expected_format == SDL_PIXELFORMAT_RGBX8888) || - (surface->format == SDL_PIXELFORMAT_ABGR8888 && expected_format == SDL_PIXELFORMAT_XBGR8888) || - (surface->format == SDL_PIXELFORMAT_BGRA8888 && expected_format == SDL_PIXELFORMAT_BGRX8888)) { + if (surface->format != expected_format && surface->format == SDL_PromotePixelFormatToAlpha(expected_format)) { surface->format = expected_format; surface->fmt = SDL_GetPixelFormatDetails(expected_format); } diff --git a/src/render/software/SDL_render_sw.c b/src/render/software/SDL_render_sw.c index ce3a3f5165..a6ebd46bbf 100644 --- a/src/render/software/SDL_render_sw.c +++ b/src/render/software/SDL_render_sw.c @@ -370,6 +370,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te int applyModulation = false; int blitRequired = false; int isOpaque = false; + SDL_PixelFormat tmp_format; if (!SDL_SurfaceValid(surface)) { return false; @@ -408,7 +409,8 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te SDL_GetSurfaceColorMod(src, &rMod, &gMod, &bMod); // SDLgfx_rotateSurface only accepts 32-bit surfaces with a 8888 layout. Everything else has to be converted. - if (!(SDL_BITSPERPIXEL(src->format) == 32 && SDL_PIXELLAYOUT(src->format) == SDL_PACKEDLAYOUT_8888)) { + tmp_format = SDL_PromotePixelFormatTo8888(src->format); + if (src->format != tmp_format) { blitRequired = true; } @@ -424,6 +426,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te // The color and alpha modulation has to be applied before the rotation when using the NONE, MOD or MUL blend modes. if ((blendmode == SDL_BLENDMODE_NONE || blendmode == SDL_BLENDMODE_MOD || blendmode == SDL_BLENDMODE_MUL) && (alphaMod & rMod & gMod & bMod) != 255) { + tmp_format = SDL_PromotePixelFormatToAlpha(tmp_format); applyModulation = true; SDL_SetSurfaceAlphaMod(src_clone, alphaMod); SDL_SetSurfaceColorMod(src_clone, rMod, gMod, bMod); @@ -438,7 +441,8 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te * to clear the pixels in the destination surface. The other steps are explained below. */ if (blendmode == SDL_BLENDMODE_NONE && !isOpaque) { - mask = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888); + SDL_PixelFormat mask_format = SDL_PromotePixelFormatToAlpha(tmp_format); + mask = SDL_CreateSurface(final_rect->w, final_rect->h, mask_format); if (!mask) { result = false; } else { @@ -451,7 +455,7 @@ static bool SW_RenderCopyEx(SDL_Renderer *renderer, SDL_Surface *surface, SDL_Te */ if (result && (blitRequired || applyModulation)) { SDL_Rect scale_rect = tmp_rect; - src_scaled = SDL_CreateSurface(final_rect->w, final_rect->h, SDL_PIXELFORMAT_ARGB8888); + src_scaled = SDL_CreateSurface(final_rect->w, final_rect->h, tmp_format); if (!src_scaled) { result = false; } else { @@ -870,7 +874,13 @@ static bool SW_RunCommandQueue(SDL_Renderer *renderer, SDL_RenderCommand *cmd, v } else { // Prevent to do scaling + clipping on viewport boundaries as it may lose proportion if (dstrect->x < 0 || dstrect->y < 0 || dstrect->x + dstrect->w > surface->w || dstrect->y + dstrect->h > surface->h) { - SDL_PixelFormat tmp_format = SDL_ISPIXELFORMAT_ALPHA(src->format) ? SDL_PIXELFORMAT_ARGB8888 : surface->format; + SDL_PixelFormat tmp_format = src->format; + + // Linear scaling expects an 8888 format - convert here to avoid extra steps later + if (cmd->data.draw.texture_scale_mode == SDL_SCALEMODE_LINEAR) { + tmp_format = SDL_PromotePixelFormatTo8888(src->format); + } + SDL_Surface *tmp = SDL_CreateSurface(dstrect->w, dstrect->h, tmp_format); // Scale to an intermediate surface, then blit if (tmp) { @@ -1055,97 +1065,20 @@ static void SW_DestroyRenderer(SDL_Renderer *renderer) static void SW_SelectBestFormats(SDL_Renderer *renderer, SDL_PixelFormat format) { + SDL_PixelFormat fmtA, fmt8A; + // Prefer the format used by the framebuffer by default. SDL_AddSupportedTextureFormat(renderer, format); - switch (format) { - case SDL_PIXELFORMAT_XRGB4444: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB4444); - break; - case SDL_PIXELFORMAT_XBGR4444: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR4444); - break; - case SDL_PIXELFORMAT_ARGB4444: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB4444); - break; - case SDL_PIXELFORMAT_ABGR4444: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR4444); - break; + // Try and find an alpha format with the same layout. + fmtA = SDL_PromotePixelFormatToAlpha(format); + if (fmtA != SDL_PIXELFORMAT_UNKNOWN && fmtA != format) + SDL_AddSupportedTextureFormat(renderer, fmtA); - case SDL_PIXELFORMAT_XRGB1555: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB1555); - break; - case SDL_PIXELFORMAT_XBGR1555: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR1555); - break; - case SDL_PIXELFORMAT_ARGB1555: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB1555); - break; - case SDL_PIXELFORMAT_ABGR1555: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR1555); - break; - - case SDL_PIXELFORMAT_XRGB8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); - break; - case SDL_PIXELFORMAT_RGBX8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA8888); - break; - case SDL_PIXELFORMAT_XBGR8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888); - break; - case SDL_PIXELFORMAT_BGRX8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA8888); - break; - case SDL_PIXELFORMAT_ARGB8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888); - break; - case SDL_PIXELFORMAT_RGBA8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX8888); - break; - case SDL_PIXELFORMAT_ABGR8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888); - break; - case SDL_PIXELFORMAT_BGRA8888: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX8888); - break; - default: - break; - } - - /* Ensure that we always have a SDL_PACKEDLAYOUT_8888 format. Having a matching component order increases the - * chances of getting a fast path for blitting. - */ - if (SDL_ISPIXELFORMAT_PACKED(format)) { - if (SDL_PIXELLAYOUT(format) != SDL_PACKEDLAYOUT_8888) { - switch (SDL_PIXELORDER(format)) { - case SDL_PACKEDORDER_BGRX: - case SDL_PACKEDORDER_BGRA: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRX8888); - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_BGRA8888); - break; - case SDL_PACKEDORDER_RGBX: - case SDL_PACKEDORDER_RGBA: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBX8888); - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_RGBA8888); - break; - case SDL_PACKEDORDER_XBGR: - case SDL_PACKEDORDER_ABGR: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XBGR8888); - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ABGR8888); - break; - case SDL_PACKEDORDER_XRGB: - case SDL_PACKEDORDER_ARGB: - default: - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888); - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); - break; - } - } - } else { - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_XRGB8888); - SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_ARGB8888); - } + // Ensure that we always have a format with an 8-bit alpha channel. + fmt8A = SDL_PromotePixelFormatToAlpha(SDL_PromotePixelFormatTo8888(format)); + if (fmt8A != SDL_PIXELFORMAT_UNKNOWN && fmt8A != format && fmt8A != fmtA) + SDL_AddSupportedTextureFormat(renderer, fmt8A); // Add 8-bit palettized format SDL_AddSupportedTextureFormat(renderer, SDL_PIXELFORMAT_INDEX8); diff --git a/src/render/software/SDL_triangle.c b/src/render/software/SDL_triangle.c index 9017559c90..53761a8a38 100644 --- a/src/render/software/SDL_triangle.c +++ b/src/render/software/SDL_triangle.c @@ -26,6 +26,7 @@ #include "SDL_triangle.h" +#include "../../video/SDL_pixels_c.h" #include "../../video/SDL_surface_c.h" /* fixed points bits precision @@ -291,11 +292,12 @@ bool SDL_SW_FillTriangle(SDL_Surface *dst, SDL_Point *d0, SDL_Point *d1, SDL_Poi } if (blend != SDL_BLENDMODE_NONE) { - SDL_PixelFormat format = dst->format; - // need an alpha format - if (!SDL_ISPIXELFORMAT_ALPHA(format)) { - format = SDL_PIXELFORMAT_ARGB8888; + SDL_PixelFormat format = SDL_PromotePixelFormatToAlpha(dst->format); + + if (format == SDL_PIXELFORMAT_UNKNOWN) { + format = SDL_PromotePixelFormatTo8888(dst->format); + format = SDL_PromotePixelFormatToAlpha(format); } // Use an intermediate surface diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 444f98e50f..8967bfceb1 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -702,6 +702,83 @@ SDL_PixelFormat SDL_GetPixelFormatForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, return SDL_PIXELFORMAT_UNKNOWN; } +SDL_PixelFormat SDL_PromotePixelFormatToAlpha(SDL_PixelFormat format) +{ + switch (format) { + case SDL_PIXELFORMAT_XRGB4444: + return SDL_PIXELFORMAT_ARGB4444; + case SDL_PIXELFORMAT_XBGR4444: + return SDL_PIXELFORMAT_ABGR4444; + case SDL_PIXELFORMAT_XRGB1555: + return SDL_PIXELFORMAT_ARGB1555; + case SDL_PIXELFORMAT_XBGR1555: + return SDL_PIXELFORMAT_ABGR1555; + case SDL_PIXELFORMAT_XRGB8888: + return SDL_PIXELFORMAT_ARGB8888; + case SDL_PIXELFORMAT_XBGR8888: + return SDL_PIXELFORMAT_ABGR8888; + case SDL_PIXELFORMAT_RGBX8888: + return SDL_PIXELFORMAT_RGBA8888; + case SDL_PIXELFORMAT_BGRX8888: + return SDL_PIXELFORMAT_BGRA8888; + case SDL_PIXELFORMAT_XRGB2101010: + return SDL_PIXELFORMAT_ARGB2101010; + case SDL_PIXELFORMAT_XBGR2101010: + return SDL_PIXELFORMAT_ABGR2101010; + default: + if (SDL_ISPIXELFORMAT_ALPHA(format)) { + return format; + } else { + return SDL_PIXELFORMAT_UNKNOWN; + } + } +} + +SDL_PixelFormat SDL_PromotePixelFormatTo8888(SDL_PixelFormat format) +{ + if (SDL_ISPIXELFORMAT_PACKED(format)) { + switch (SDL_PIXELORDER(format)) { + case SDL_PACKEDORDER_BGRX: + return SDL_PIXELFORMAT_BGRX8888; + case SDL_PACKEDORDER_BGRA: + return SDL_PIXELFORMAT_BGRA8888; + case SDL_PACKEDORDER_RGBX: + return SDL_PIXELFORMAT_RGBX8888; + case SDL_PACKEDORDER_RGBA: + return SDL_PIXELFORMAT_RGBA8888; + case SDL_PACKEDORDER_XBGR: + return SDL_PIXELFORMAT_XBGR8888; + case SDL_PACKEDORDER_ABGR: + return SDL_PIXELFORMAT_ABGR8888; + case SDL_PACKEDORDER_XRGB: + return SDL_PIXELFORMAT_XRGB8888; + case SDL_PACKEDORDER_ARGB: + return SDL_PIXELFORMAT_ARGB8888; + default: + break; + } + } else if (SDL_ISPIXELFORMAT_ARRAY(format)) { + switch (SDL_PIXELORDER(format)) { + case SDL_ARRAYORDER_RGB: + return SDL_PIXELFORMAT_RGBX32; + case SDL_ARRAYORDER_RGBA: + return SDL_PIXELFORMAT_RGBA32; + case SDL_ARRAYORDER_ARGB: + return SDL_PIXELFORMAT_ARGB32; + case SDL_ARRAYORDER_BGR: + return SDL_PIXELFORMAT_BGRX32; + case SDL_ARRAYORDER_BGRA: + return SDL_PIXELFORMAT_BGRA32; + case SDL_ARRAYORDER_ABGR: + return SDL_PIXELFORMAT_ABGR32; + default: + break; + } + } + + return SDL_PIXELFORMAT_ARGB8888; +} + static SDL_InitState SDL_format_details_init; static SDL_HashTable *SDL_format_details; diff --git a/src/video/SDL_pixels_c.h b/src/video/SDL_pixels_c.h index e851386c08..f6edfac97e 100644 --- a/src/video/SDL_pixels_c.h +++ b/src/video/SDL_pixels_c.h @@ -29,6 +29,8 @@ // Pixel format functions +extern SDL_PixelFormat SDL_PromotePixelFormatToAlpha(SDL_PixelFormat format); +extern SDL_PixelFormat SDL_PromotePixelFormatTo8888(SDL_PixelFormat format); extern void SDL_Get8888AlphaMaskAndShift(const SDL_PixelFormatDetails *fmt, Uint32 *mask, Uint32 *shift); extern SDL_Colorspace SDL_GetDefaultColorspaceForFormat(SDL_PixelFormat pixel_format); extern void SDL_QuitPixelFormatDetails(void); diff --git a/src/video/SDL_rotate.c b/src/video/SDL_rotate.c index c5071b525f..3a17143b00 100644 --- a/src/video/SDL_rotate.c +++ b/src/video/SDL_rotate.c @@ -30,6 +30,7 @@ Andreas Schiffler -- aschiffler at ferzkopp dot net */ #include "SDL_internal.h" +#include "SDL_pixels_c.h" #include "SDL_surface_c.h" #include "SDL_rotate.h" @@ -500,8 +501,7 @@ SDL_Surface *SDLgfx_rotateSurface(SDL_Surface *src, double angle, int smooth, in } // This function requires a 32-bit surface or 8-bit surface with a colorkey is8bit = (src->format == SDL_PIXELFORMAT_INDEX8) && colorKeyAvailable; - if (!is8bit && - !(SDL_BITSPERPIXEL(src->format) == 32 && SDL_PIXELLAYOUT(src->format) == SDL_PACKEDLAYOUT_8888)) { + if (!is8bit && src->format != SDL_PromotePixelFormatTo8888(src->format)) { return NULL; } diff --git a/src/video/SDL_stretch.c b/src/video/SDL_stretch.c index d432c0fbbd..513de9b712 100644 --- a/src/video/SDL_stretch.c +++ b/src/video/SDL_stretch.c @@ -20,6 +20,7 @@ */ #include "SDL_internal.h" +#include "SDL_pixels_c.h" #include "SDL_surface_c.h" static bool SDL_StretchSurfaceUncheckedNearest(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface *dst, const SDL_Rect *dstrect); @@ -93,7 +94,7 @@ bool SDL_StretchSurface(SDL_Surface *src, const SDL_Rect *srcrect, SDL_Surface * } if (scaleMode == SDL_SCALEMODE_LINEAR) { - if (SDL_BYTESPERPIXEL(src->format) != 4 || src->format == SDL_PIXELFORMAT_ARGB2101010) { + if (src->format != SDL_PromotePixelFormatTo8888(src->format)) { return SDL_SetError("Wrong format"); } } diff --git a/src/video/SDL_surface.c b/src/video/SDL_surface.c index 6a03fad732..52b87e7ee8 100644 --- a/src/video/SDL_surface.c +++ b/src/video/SDL_surface.c @@ -1277,9 +1277,7 @@ bool SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, S } else { if (!(src->map.info.flags & complex_copy_flags) && src->format == dst->format && - !SDL_ISPIXELFORMAT_INDEXED(src->format) && - SDL_BYTESPERPIXEL(src->format) == 4 && - src->format != SDL_PIXELFORMAT_ARGB2101010) { + src->format == SDL_PromotePixelFormatTo8888(src->format)) { // fast path return SDL_StretchSurface(src, srcrect, dst, dstrect, SDL_SCALEMODE_LINEAR); } else if (SDL_BITSPERPIXEL(src->format) < 8) { @@ -1312,13 +1310,10 @@ bool SDL_BlitSurfaceUncheckedScaled(SDL_Surface *src, const SDL_Rect *srcrect, S srcrect2.h = srcrect->h; // Change source format if not appropriate for scaling - if (SDL_BYTESPERPIXEL(src->format) != 4 || src->format == SDL_PIXELFORMAT_ARGB2101010) { - SDL_PixelFormat fmt; - if (SDL_BYTESPERPIXEL(dst->format) == 4 && dst->format != SDL_PIXELFORMAT_ARGB2101010 && - (SDL_ISPIXELFORMAT_ALPHA(dst->format) || !is_complex_copy_flags)) { - fmt = dst->format; - } else { - fmt = SDL_PIXELFORMAT_ARGB8888; + if (src->format != SDL_PromotePixelFormatTo8888(src->format)) { + SDL_PixelFormat fmt = SDL_PromotePixelFormatTo8888(dst->format); + if (!SDL_ISPIXELFORMAT_ALPHA(fmt) || is_complex_copy_flags) { + fmt = SDL_PromotePixelFormatToAlpha(fmt); } tmp1 = SDL_ConvertSurfaceRect(src, srcrect, fmt); if (!tmp1) { @@ -2189,11 +2184,11 @@ SDL_Surface *SDL_RotateSurface(SDL_Surface *surface, float angle) SDLgfx_rotozoomSurfaceSizeTrig(surface->w, surface->h, angle, ¢er, &rect_dest, &cangle, &sangle); // This function requires a 32-bit surface or 8-bit surface with a colorkey - if ((SDL_BITSPERPIXEL(surface->format) == 32 && SDL_PIXELLAYOUT(surface->format) == SDL_PACKEDLAYOUT_8888) || + if ((surface->format == SDL_PromotePixelFormatTo8888(surface->format)) || (surface->format == SDL_PIXELFORMAT_INDEX8 && SDL_SurfaceHasColorKey(surface))) { rotated = SDLgfx_rotateSurface(surface, angle, 1, 0, 0, &rect_dest, cangle, sangle, ¢er); } else { - SDL_Surface *convert = SDL_ConvertSurface(surface, SDL_PIXELFORMAT_RGBA32); + SDL_Surface *convert = SDL_ConvertSurface(surface, SDL_PromotePixelFormatTo8888(surface->format)); if (convert) { SDL_Surface *tmp = SDLgfx_rotateSurface(convert, angle, 1, 0, 0, &rect_dest, cangle, sangle, ¢er); if (tmp) { @@ -2593,7 +2588,7 @@ static bool SDL_PremultiplyAlphaPixelsAndColorspace(int width, int height, SDL_P src_format == SDL_PIXELFORMAT_BGRA8888) { format = src_format; } else { - format = SDL_PIXELFORMAT_ARGB8888; + format = SDL_PromotePixelFormatTo8888(dst_format); } } if (linear) { diff --git a/src/video/SDL_yuv.c b/src/video/SDL_yuv.c index 6b57d54dc1..d5852d7991 100644 --- a/src/video/SDL_yuv.c +++ b/src/video/SDL_yuv.c @@ -641,7 +641,9 @@ bool SDL_ConvertPixels_YUV_to_RGB(int width, int height, return result; } - if (dst_format != SDL_PIXELFORMAT_ARGB8888) { + // TODO: Use RGB565 or RGB24 for smaller pixel formats? + SDL_PixelFormat tmp_format = SDL_PromotePixelFormatTo8888(dst_format); + if (dst_format != tmp_format) { bool result; void *tmp; int tmp_pitch = (width * sizeof(Uint32)); @@ -651,15 +653,15 @@ bool SDL_ConvertPixels_YUV_to_RGB(int width, int height, return false; } - // convert src/src_format to tmp/ARGB8888 - result = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src_properties, src, src_pitch, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch); + // convert src/src_format to tmp/8888 + result = SDL_ConvertPixels_YUV_to_RGB(width, height, src_format, src_colorspace, src_properties, src, src_pitch, tmp_format, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch); if (!result) { SDL_free(tmp); return false; } - // convert tmp/ARGB8888 to dst/RGB - result = SDL_ConvertPixelsAndColorspace(width, height, SDL_PIXELFORMAT_ARGB8888, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch); + // convert tmp/8888 to dst/dst_format + result = SDL_ConvertPixelsAndColorspace(width, height, tmp_format, SDL_COLORSPACE_SRGB, 0, tmp, tmp_pitch, dst_format, dst_colorspace, dst_properties, dst, dst_pitch); SDL_free(tmp); return result; } From 477ed722beca0b0bd560306ca8a904cc5414fca4 Mon Sep 17 00:00:00 2001 From: Cameron Cawley Date: Wed, 13 May 2026 18:37:07 +0100 Subject: [PATCH 2/2] Add fast paths for BGR555 and BGR565 normal blits --- src/video/SDL_blit_N.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index b014d4233a..1766edc9d7 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -2998,6 +2998,14 @@ static const struct blit_table normal_blit_2[] = { 0, Blit_RGB565_RGBA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, { 0x0000F800, 0x000007E0, 0x0000001F, 4, 0x0000FF00, 0x00FF0000, 0xFF000000, 0, Blit_RGB565_BGRA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + { 0x0000001F, 0x000007E0, 0x0000F800, 4, 0x000000FF, 0x0000FF00, 0x00FF0000, + 0, Blit_RGB565_ARGB8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + { 0x0000001F, 0x000007E0, 0x0000F800, 4, 0x00FF0000, 0x0000FF00, 0x000000FF, + 0, Blit_RGB565_ABGR8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + { 0x0000001F, 0x000007E0, 0x0000F800, 4, 0x0000FF00, 0x00FF0000, 0xFF000000, + 0, Blit_RGB565_RGBA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, + { 0x0000001F, 0x000007E0, 0x0000F800, 4, 0xFF000000, 0x00FF0000, 0x0000FF00, + 0, Blit_RGB565_BGRA8888, NO_ALPHA | COPY_ALPHA | SET_ALPHA }, #endif // Default for 16-bit RGB source, used if no other blitter matches { 0, 0, 0, 0, 0, 0, 0, 0, BlitNtoN, 0 } @@ -3077,8 +3085,12 @@ static const struct blit_table normal_blit_4[] = { // RGB 888 and RGB 565 { 0x00FF0000, 0x0000FF00, 0x000000FF, 2, 0x0000F800, 0x000007E0, 0x0000001F, 0, Blit_XRGB8888_RGB565, NO_ALPHA }, + { 0x000000FF, 0x0000FF00, 0x00FF0000, 2, 0x0000001F, 0x000007E0, 0x0000F800, + 0, Blit_XRGB8888_RGB565, NO_ALPHA }, { 0x00FF0000, 0x0000FF00, 0x000000FF, 2, 0x00007C00, 0x000003E0, 0x0000001F, 0, Blit_XRGB8888_RGB555, NO_ALPHA }, + { 0x000000FF, 0x0000FF00, 0x00FF0000, 2, 0x0000001F, 0x000003E0, 0x00007C00, + 0, Blit_XRGB8888_RGB555, NO_ALPHA }, // Default for 32-bit RGB source, used if no other blitter matches { 0, 0, 0, 0, 0, 0, 0, 0, BlitNtoN, 0 } };