From 5f176a7b96880600ba6aabe096a935a994091ea0 Mon Sep 17 00:00:00 2001 From: Sam Lantinga Date: Mon, 6 Nov 2023 00:21:26 -0800 Subject: [PATCH] Added 10-bit pixel formats in addition to SDL_PIXELFORMAT_ARGB2101010 Added SDL_PIXELFORMAT_XRGB2101010, SDL_PIXELFORMAT_XBGR2101010, SDL_PIXELFORMAT_ABGR2101010 Fixes https://github.com/libsdl-org/SDL/issues/3553 --- include/SDL3/SDL_pixels.h | 13 +++++++++++ src/video/SDL_blit.h | 15 ++++++++++++ src/video/SDL_blit_N.c | 24 +++++++++---------- src/video/SDL_blit_slow.c | 44 +++++++++++++++++++++++++++++++---- src/video/SDL_pixels.c | 36 ++++++++++++++++++++++++++++ test/testautomation_pixels.c | 6 +++++ test/testautomation_surface.c | 3 +++ 7 files changed, 124 insertions(+), 17 deletions(-) diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h index 82d4feb338006..8f7086d9af519 100644 --- a/include/SDL3/SDL_pixels.h +++ b/include/SDL3/SDL_pixels.h @@ -190,6 +190,10 @@ typedef enum (SDL_PIXELORDER(format) == SDL_PACKEDORDER_ABGR) || \ (SDL_PIXELORDER(format) == SDL_PACKEDORDER_BGRA)))) +#define SDL_ISPIXELFORMAT_10BIT(format) \ + ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_PACKED32) && \ + (SDL_PIXELLAYOUT(format) == SDL_PACKEDLAYOUT_2101010)) + /* The flag is set to 1 because 0x1? is not in the printable ASCII range */ #define SDL_ISPIXELFORMAT_FOURCC(format) \ ((format) && (SDL_PIXELFLAG(format) != 1)) @@ -291,9 +295,18 @@ typedef enum SDL_PIXELFORMAT_BGRA8888 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_BGRA, SDL_PACKEDLAYOUT_8888, 32, 4), + SDL_PIXELFORMAT_XRGB2101010 = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XRGB, + SDL_PACKEDLAYOUT_2101010, 32, 4), + SDL_PIXELFORMAT_XBGR2101010 = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_XBGR, + SDL_PACKEDLAYOUT_2101010, 32, 4), SDL_PIXELFORMAT_ARGB2101010 = SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ARGB, SDL_PACKEDLAYOUT_2101010, 32, 4), + SDL_PIXELFORMAT_ABGR2101010 = + SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_PACKED32, SDL_PACKEDORDER_ABGR, + SDL_PACKEDLAYOUT_2101010, 32, 4), /* Aliases for RGBA byte arrays of color data, for the current platform */ #if SDL_BYTEORDER == SDL_BIG_ENDIAN diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h index 0568dce3f0cf2..759d005b8b236 100644 --- a/src/video/SDL_blit.h +++ b/src/video/SDL_blit.h @@ -260,6 +260,14 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface); a = (a * 3) / 255; \ Pixel = (a << 30) | (r << 20) | (g << 10) | b; \ } +#define ABGR2101010_FROM_RGBA(Pixel, r, g, b, a) \ + { \ + r = r ? ((r << 2) | 0x3) : 0; \ + g = g ? ((g << 2) | 0x3) : 0; \ + b = b ? ((b << 2) | 0x3) : 0; \ + a = (a * 3) / 255; \ + Pixel = (a << 30) | (b << 20) | (g << 10) | r; \ + } #define ASSEMBLE_RGB(buf, bpp, fmt, r, g, b) \ { \ switch (bpp) { \ @@ -352,6 +360,13 @@ extern SDL_BlitFunc SDL_CalculateBlitA(SDL_Surface *surface); b = ((Pixel >> 2) & 0xFF); \ a = SDL_expand_byte[6][(Pixel >> 30)]; \ } +#define RGBA_FROM_ABGR2101010(Pixel, r, g, b, a) \ + { \ + r = ((Pixel >> 2) & 0xFF); \ + g = ((Pixel >> 12) & 0xFF); \ + b = ((Pixel >> 22) & 0xFF); \ + a = SDL_expand_byte[6][(Pixel >> 30)]; \ + } #define DISEMBLE_RGBA(buf, bpp, fmt, Pixel, r, g, b, a) \ do { \ switch (bpp) { \ diff --git a/src/video/SDL_blit_N.c b/src/video/SDL_blit_N.c index bf7c910763613..4c1f8c3e3997c 100644 --- a/src/video/SDL_blit_N.c +++ b/src/video/SDL_blit_N.c @@ -2327,8 +2327,8 @@ static void BlitNtoN(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int alpha_channel, p0, p1, p2, p3; @@ -2356,7 +2356,7 @@ static void BlitNtoN(SDL_BlitInfo *info) /* Blit with permutation: 4->3 */ if (srcbpp == 4 && dstbpp == 3 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; @@ -2382,7 +2382,7 @@ static void BlitNtoN(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 3->4 */ if (srcbpp == 3 && dstbpp == 4 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int alpha_channel, p0, p1, p2, p3; @@ -2445,8 +2445,8 @@ static void BlitNtoNCopyAlpha(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; @@ -2651,8 +2651,8 @@ static void BlitNtoNKey(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int alpha_channel, p0, p1, p2, p3; @@ -2760,7 +2760,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info) /* Blit with permutation: 4->3 */ if (srcbpp == 4 && dstbpp == 3 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; @@ -2789,7 +2789,7 @@ static void BlitNtoNKey(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 3->4 */ if (srcbpp == 3 && dstbpp == 4 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { #if SDL_BYTEORDER == SDL_LIL_ENDIAN Uint8 k0 = ckey & 0xFF; @@ -2909,8 +2909,8 @@ static void BlitNtoNKeyCopyAlpha(SDL_BlitInfo *info) #if HAVE_FAST_WRITE_INT8 /* Blit with permutation: 4->4 */ if (srcbpp == 4 && dstbpp == 4 && - srcfmt->format != SDL_PIXELFORMAT_ARGB2101010 && - dstfmt->format != SDL_PIXELFORMAT_ARGB2101010) { + !SDL_ISPIXELFORMAT_10BIT(srcfmt->format) && + !SDL_ISPIXELFORMAT_10BIT(dstfmt->format)) { /* Find the appropriate permutation */ int p0, p1, p2, p3; diff --git a/src/video/SDL_blit_slow.c b/src/video/SDL_blit_slow.c index 3c2730c05a378..d4d3d43bac847 100644 --- a/src/video/SDL_blit_slow.c +++ b/src/video/SDL_blit_slow.c @@ -30,7 +30,7 @@ #define FORMAT_HAS_NO_ALPHA(format) format < 0 static int detect_format(SDL_PixelFormat *pf) { - if (pf->format == SDL_PIXELFORMAT_ARGB2101010) { + if (SDL_ISPIXELFORMAT_10BIT(pf->format)) { return FORMAT_2101010; } else if (pf->Amask) { return FORMAT_ALPHA; @@ -88,9 +88,27 @@ void SDL_Blit_Slow(SDL_BlitInfo *info) DISEMBLE_RGB(src, srcbpp, src_fmt, srcpixel, srcR, srcG, srcB); srcA = 0xFF; } else { - /* SDL_PIXELFORMAT_ARGB2101010 */ + /* 10-bit pixel format */ srcpixel = *((Uint32 *)(src)); - RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA); + switch (src_fmt->format) { + case SDL_PIXELFORMAT_XRGB2101010: + RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA); + srcA = 0xFF; + break; + case SDL_PIXELFORMAT_XBGR2101010: + RGBA_FROM_ABGR2101010(srcpixel, srcR, srcG, srcB, srcA); + srcA = 0xFF; + break; + case SDL_PIXELFORMAT_ARGB2101010: + RGBA_FROM_ARGB2101010(srcpixel, srcR, srcG, srcB, srcA); + break; + case SDL_PIXELFORMAT_ABGR2101010: + RGBA_FROM_ABGR2101010(srcpixel, srcR, srcG, srcB, srcA); + break; + default: + srcR = srcG = srcB = srcA = 0; + break; + } } if (flags & SDL_COPY_COLORKEY) { @@ -189,9 +207,25 @@ void SDL_Blit_Slow(SDL_BlitInfo *info) } else if (FORMAT_HAS_NO_ALPHA(dstfmt_val)) { ASSEMBLE_RGB(dst, dstbpp, dst_fmt, dstR, dstG, dstB); } else { - /* SDL_PIXELFORMAT_ARGB2101010 */ + /* 10-bit pixel format */ Uint32 pixel; - ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA); + switch (dst_fmt->format) { + case SDL_PIXELFORMAT_XRGB2101010: + dstA = 0xFF; + SDL_FALLTHROUGH; + case SDL_PIXELFORMAT_ARGB2101010: + ARGB2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA); + break; + case SDL_PIXELFORMAT_XBGR2101010: + dstA = 0xFF; + SDL_FALLTHROUGH; + case SDL_PIXELFORMAT_ABGR2101010: + ABGR2101010_FROM_RGBA(pixel, dstR, dstG, dstB, dstA); + break; + default: + pixel = 0; + break; + } *(Uint32 *)dst = pixel; } posx += incx; diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c index 7c31a24b4f0b3..f9e79bfd42ae0 100644 --- a/src/video/SDL_pixels.c +++ b/src/video/SDL_pixels.c @@ -117,7 +117,10 @@ const char *SDL_GetPixelFormatName(Uint32 format) CASE(SDL_PIXELFORMAT_RGBA8888) CASE(SDL_PIXELFORMAT_ABGR8888) CASE(SDL_PIXELFORMAT_BGRA8888) + CASE(SDL_PIXELFORMAT_XRGB2101010) + CASE(SDL_PIXELFORMAT_XBGR2101010) CASE(SDL_PIXELFORMAT_ARGB2101010) + CASE(SDL_PIXELFORMAT_ABGR2101010) CASE(SDL_PIXELFORMAT_YV12) CASE(SDL_PIXELFORMAT_IYUV) CASE(SDL_PIXELFORMAT_YUY2) @@ -440,6 +443,20 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3 #endif } break; + case 30: + if (Rmask == 0x3FF00000 && + Gmask == 0x000FFC00 && + Bmask == 0x000003FF && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XRGB2101010; + } + if (Rmask == 0x000003FF && + Gmask == 0x000FFC00 && + Bmask == 0x3FF00000 && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XBGR2101010; + } + break; case 32: if (Rmask == 0) { return SDL_PIXELFORMAT_XRGB8888; @@ -492,12 +509,31 @@ Uint32 SDL_GetPixelFormatEnumForMasks(int bpp, Uint32 Rmask, Uint32 Gmask, Uint3 Amask == 0x000000FF) { return SDL_PIXELFORMAT_BGRA8888; } + if (Rmask == 0x3FF00000 && + Gmask == 0x000FFC00 && + Bmask == 0x000003FF && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XRGB2101010; + } + if (Rmask == 0x000003FF && + Gmask == 0x000FFC00 && + Bmask == 0x3FF00000 && + Amask == 0x00000000) { + return SDL_PIXELFORMAT_XBGR2101010; + } if (Rmask == 0x3FF00000 && Gmask == 0x000FFC00 && Bmask == 0x000003FF && Amask == 0xC0000000) { return SDL_PIXELFORMAT_ARGB2101010; } + if (Rmask == 0x000003FF && + Gmask == 0x000FFC00 && + Bmask == 0x3FF00000 && + Amask == 0xC0000000) { + return SDL_PIXELFORMAT_ABGR2101010; + } + break; } return SDL_PIXELFORMAT_UNKNOWN; } diff --git a/test/testautomation_pixels.c b/test/testautomation_pixels.c index 9980b561b28d1..f05c9a981398b 100644 --- a/test/testautomation_pixels.c +++ b/test/testautomation_pixels.c @@ -39,7 +39,10 @@ static const Uint32 g_AllFormats[] = { SDL_PIXELFORMAT_RGBA8888, SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_BGRA8888, + SDL_PIXELFORMAT_XRGB2101010, + SDL_PIXELFORMAT_XBGR2101010, SDL_PIXELFORMAT_ARGB2101010, + SDL_PIXELFORMAT_ABGR2101010, SDL_PIXELFORMAT_YV12, SDL_PIXELFORMAT_IYUV, SDL_PIXELFORMAT_YUY2, @@ -81,7 +84,10 @@ static const char *g_AllFormatsVerbose[] = { "SDL_PIXELFORMAT_RGBA8888", "SDL_PIXELFORMAT_ABGR8888", "SDL_PIXELFORMAT_BGRA8888", + "SDL_PIXELFORMAT_XRGB2101010", + "SDL_PIXELFORMAT_XBGR2101010", "SDL_PIXELFORMAT_ARGB2101010", + "SDL_PIXELFORMAT_ABGR2101010", "SDL_PIXELFORMAT_YV12", "SDL_PIXELFORMAT_IYUV", "SDL_PIXELFORMAT_YUY2", diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c index acde6396c561f..e338927e74790 100644 --- a/test/testautomation_surface.c +++ b/test/testautomation_surface.c @@ -327,7 +327,10 @@ static int surface_testCompleteSurfaceConversion(void *arg) SDL_PIXELFORMAT_RGBA8888, SDL_PIXELFORMAT_ABGR8888, SDL_PIXELFORMAT_BGRA8888, + SDL_PIXELFORMAT_XRGB2101010, + SDL_PIXELFORMAT_XBGR2101010, SDL_PIXELFORMAT_ARGB2101010, + SDL_PIXELFORMAT_ABGR2101010, }; SDL_Surface *face = NULL, *cvt1, *cvt2, *final; SDL_PixelFormat *fmt1, *fmt2;