Browse Source

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
Sam Lantinga 1 year ago
parent
commit
f7d40b7594

+ 13 - 0
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

+ 15 - 0
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) {                                  \

+ 12 - 12
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;

+ 39 - 5
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;

+ 36 - 0
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;
 }

+ 6 - 0
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",

+ 3 - 0
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;