From 68e9fbe0a9086d781e80c6865775c91b9292603a Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Sun, 7 Sep 2025 21:15:51 -0700 Subject: [PATCH] Added SDL_GetPixelFormatFromGPUTextureFormat() and SDL_GetGPUTextureFormatFromPixelFormat() Fixes https://github.com/libsdl-org/SDL/issues/13899 --- include/SDL3/SDL_gpu.h | 20 ++++++++++ src/dynapi/SDL_dynapi.sym | 2 + src/dynapi/SDL_dynapi_overrides.h | 2 + src/dynapi/SDL_dynapi_procs.h | 2 + src/gpu/SDL_gpu.c | 65 +++++++++++++++++++++++++++++++ src/render/gpu/SDL_render_gpu.c | 61 +---------------------------- 6 files changed, 93 insertions(+), 59 deletions(-) diff --git a/include/SDL3/SDL_gpu.h b/include/SDL3/SDL_gpu.h index 2af19fa2e9cdf..3ab5b82238c97 100644 --- a/include/SDL3/SDL_gpu.h +++ b/include/SDL3/SDL_gpu.h @@ -4420,6 +4420,26 @@ extern SDL_DECLSPEC Uint32 SDLCALL SDL_CalculateGPUTextureFormatSize( Uint32 height, Uint32 depth_or_layer_count); +/** + * Get the SDL pixel format corresponding to a GPU texture format. + * + * \param format a texture format. + * \returns the corresponding pixel format, or SDL_PIXELFORMAT_UNKNOWN if there is no corresponding pixel format. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_PixelFormat SDLCALL SDL_GetPixelFormatFromGPUTextureFormat(SDL_GPUTextureFormat format); + +/** + * Get the GPU texture format corresponding to an SDL pixel format. + * + * \param format a pixel format. + * \returns the corresponding GPU texture format, or SDL_GPU_TEXTUREFORMAT_INVALID if there is no corresponding GPU texture format. + * + * \since This function is available since SDL 3.4.0. + */ +extern SDL_DECLSPEC SDL_GPUTextureFormat SDLCALL SDL_GetGPUTextureFormatFromPixelFormat(SDL_PixelFormat format); + #ifdef SDL_PLATFORM_GDK /** diff --git a/src/dynapi/SDL_dynapi.sym b/src/dynapi/SDL_dynapi.sym index 0627fe9ed701e..0e4b0aa6d89a3 100644 --- a/src/dynapi/SDL_dynapi.sym +++ b/src/dynapi/SDL_dynapi.sym @@ -1255,6 +1255,8 @@ SDL3_0.0.0 { SDL_PutAudioStreamDataNoCopy; SDL_AddAtomicU32; SDL_hid_get_properties; + SDL_GetPixelFormatFromGPUTextureFormat; + SDL_GetGPUTextureFormatFromPixelFormat; # extra symbols go here (don't modify this line) local: *; }; diff --git a/src/dynapi/SDL_dynapi_overrides.h b/src/dynapi/SDL_dynapi_overrides.h index c0749418583ab..686e5472ed930 100644 --- a/src/dynapi/SDL_dynapi_overrides.h +++ b/src/dynapi/SDL_dynapi_overrides.h @@ -1280,3 +1280,5 @@ #define SDL_PutAudioStreamDataNoCopy SDL_PutAudioStreamDataNoCopy_REAL #define SDL_AddAtomicU32 SDL_AddAtomicU32_REAL #define SDL_hid_get_properties SDL_hid_get_properties_REAL +#define SDL_GetPixelFormatFromGPUTextureFormat SDL_GetPixelFormatFromGPUTextureFormat_REAL +#define SDL_GetGPUTextureFormatFromPixelFormat SDL_GetGPUTextureFormatFromPixelFormat_REAL diff --git a/src/dynapi/SDL_dynapi_procs.h b/src/dynapi/SDL_dynapi_procs.h index 9876a3de8dd57..8516bfe26a0b7 100644 --- a/src/dynapi/SDL_dynapi_procs.h +++ b/src/dynapi/SDL_dynapi_procs.h @@ -1288,3 +1288,5 @@ SDL_DYNAPI_PROC(int,SDL_GetEventDescription,(const SDL_Event *a,char *b,int c),( SDL_DYNAPI_PROC(bool,SDL_PutAudioStreamDataNoCopy,(SDL_AudioStream *a,const void *b,int c,SDL_AudioStreamDataCompleteCallback d,void *e),(a,b,c,d,e),return) SDL_DYNAPI_PROC(Uint32,SDL_AddAtomicU32,(SDL_AtomicU32 *a,int b),(a,b),return) SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_hid_get_properties,(SDL_hid_device *a),(a),return) +SDL_DYNAPI_PROC(SDL_PixelFormat,SDL_GetPixelFormatFromGPUTextureFormat,(SDL_GPUTextureFormat a),(a),return) +SDL_DYNAPI_PROC(SDL_GPUTextureFormat,SDL_GetGPUTextureFormatFromPixelFormat,(SDL_PixelFormat a),(a),return) diff --git a/src/gpu/SDL_gpu.c b/src/gpu/SDL_gpu.c index dfc5f8a26b00c..ede4c54117c44 100644 --- a/src/gpu/SDL_gpu.c +++ b/src/gpu/SDL_gpu.c @@ -3344,3 +3344,68 @@ Uint32 SDL_CalculateGPUTextureFormatSize( Uint32 blocksPerColumn = (height + blockHeight - 1) / blockHeight; return depth_or_layer_count * blocksPerRow * blocksPerColumn * SDL_GPUTextureFormatTexelBlockSize(format); } + +SDL_PixelFormat SDL_GetPixelFormatFromGPUTextureFormat(SDL_GPUTextureFormat format) +{ + switch (format) { + case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM: + return SDL_PIXELFORMAT_BGRA4444; + case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM: + return SDL_PIXELFORMAT_BGR565; + case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM: + return SDL_PIXELFORMAT_BGRA5551; + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: + return SDL_PIXELFORMAT_RGBA32; + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM: + return SDL_PIXELFORMAT_RGBA32; + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM: + return SDL_PIXELFORMAT_RGBA32; + case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB: + return SDL_PIXELFORMAT_RGBA32; + case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM: + return SDL_PIXELFORMAT_BGRA32; + case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB: + return SDL_PIXELFORMAT_BGRA32; + case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM: + return SDL_PIXELFORMAT_ABGR2101010; + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: + return SDL_PIXELFORMAT_RGBA64; + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM: + return SDL_PIXELFORMAT_RGBA64; + case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT: + return SDL_PIXELFORMAT_RGBA64_FLOAT; + case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT: + return SDL_PIXELFORMAT_RGBA128_FLOAT; + default: + return SDL_PIXELFORMAT_UNKNOWN; + } +} + +SDL_GPUTextureFormat SDL_GetGPUTextureFormatFromPixelFormat(SDL_PixelFormat format) +{ + switch (format) { + case SDL_PIXELFORMAT_BGRA4444: + return SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM; + case SDL_PIXELFORMAT_BGR565: + return SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM; + case SDL_PIXELFORMAT_BGRA5551: + return SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM; + case SDL_PIXELFORMAT_BGRA32: + case SDL_PIXELFORMAT_BGRX32: + return SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; + case SDL_PIXELFORMAT_RGBA32: + case SDL_PIXELFORMAT_RGBX32: + return SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; + case SDL_PIXELFORMAT_ABGR2101010: + return SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM; + case SDL_PIXELFORMAT_RGBA64: + return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM; + case SDL_PIXELFORMAT_RGBA64_FLOAT: + return SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT; + case SDL_PIXELFORMAT_RGBA128_FLOAT: + return SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT; + default: + return SDL_GPU_TEXTUREFORMAT_INVALID; + } +} + diff --git a/src/render/gpu/SDL_render_gpu.c b/src/render/gpu/SDL_render_gpu.c index 9d11b6d85b74d..8758ef44b0092 100644 --- a/src/render/gpu/SDL_render_gpu.c +++ b/src/render/gpu/SDL_render_gpu.c @@ -117,63 +117,6 @@ static bool GPU_SupportsBlendMode(SDL_Renderer *renderer, SDL_BlendMode blendMod return true; } -static SDL_GPUTextureFormat PixFormatToTexFormat(SDL_PixelFormat pixel_format) -{ - switch (pixel_format) { - case SDL_PIXELFORMAT_BGRA32: - case SDL_PIXELFORMAT_BGRX32: - return SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM; - case SDL_PIXELFORMAT_RGBA32: - case SDL_PIXELFORMAT_RGBX32: - return SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM; - - // YUV TODO - case SDL_PIXELFORMAT_YV12: - case SDL_PIXELFORMAT_IYUV: - case SDL_PIXELFORMAT_NV12: - case SDL_PIXELFORMAT_NV21: - case SDL_PIXELFORMAT_UYVY: - default: - return SDL_GPU_TEXTUREFORMAT_INVALID; - } -} - -static SDL_PixelFormat TexFormatToPixFormat(SDL_GPUTextureFormat tex_format) -{ - switch (tex_format) { - case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM: - return SDL_PIXELFORMAT_RGBA32; - case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM: - return SDL_PIXELFORMAT_BGRA32; - case SDL_GPU_TEXTUREFORMAT_B5G6R5_UNORM: - return SDL_PIXELFORMAT_BGR565; - case SDL_GPU_TEXTUREFORMAT_B5G5R5A1_UNORM: - return SDL_PIXELFORMAT_BGRA5551; - case SDL_GPU_TEXTUREFORMAT_B4G4R4A4_UNORM: - return SDL_PIXELFORMAT_BGRA4444; - case SDL_GPU_TEXTUREFORMAT_R10G10B10A2_UNORM: - return SDL_PIXELFORMAT_ABGR2101010; - case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UNORM: - return SDL_PIXELFORMAT_RGBA64; - case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_SNORM: - return SDL_PIXELFORMAT_RGBA32; - case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_FLOAT: - return SDL_PIXELFORMAT_RGBA64_FLOAT; - case SDL_GPU_TEXTUREFORMAT_R32G32B32A32_FLOAT: - return SDL_PIXELFORMAT_RGBA128_FLOAT; - case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UINT: - return SDL_PIXELFORMAT_RGBA32; - case SDL_GPU_TEXTUREFORMAT_R16G16B16A16_UINT: - return SDL_PIXELFORMAT_RGBA64; - case SDL_GPU_TEXTUREFORMAT_R8G8B8A8_UNORM_SRGB: - return SDL_PIXELFORMAT_RGBA32; - case SDL_GPU_TEXTUREFORMAT_B8G8R8A8_UNORM_SRGB: - return SDL_PIXELFORMAT_BGRA32; - default: - return SDL_PIXELFORMAT_UNKNOWN; - } -} - static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_PropertiesID create_props) { GPU_RenderData *renderdata = (GPU_RenderData *)renderer->internal; @@ -181,7 +124,7 @@ static bool GPU_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SDL_ SDL_GPUTextureFormat format; SDL_GPUTextureUsageFlags usage = SDL_GPU_TEXTUREUSAGE_SAMPLER; - format = PixFormatToTexFormat(texture->format); + format = SDL_GetGPUTextureFormatFromPixelFormat(texture->format); if (format == SDL_GPU_TEXTUREFORMAT_INVALID) { return SDL_SetError("Texture format %s not supported by SDL_GPU", @@ -948,7 +891,7 @@ static SDL_Surface *GPU_RenderReadPixels(SDL_Renderer *renderer, const SDL_Rect pixfmt = texture->format; } else { gpu_tex = data->backbuffer.texture; - pixfmt = TexFormatToPixFormat(data->backbuffer.format); + pixfmt = SDL_GetPixelFormatFromGPUTextureFormat(data->backbuffer.format); if (pixfmt == SDL_PIXELFORMAT_UNKNOWN) { SDL_SetError("Unsupported backbuffer format");