SDL: Add SDL_PIXELFORMAT_INDEX2LSB and SDL_PIXELFORMAT_INDEX2MSB (67eb0)

From 67eb03400a100853bcacdca960deabe31f9c98f3 Mon Sep 17 00:00:00 2001
From: Cameron Cawley <[EMAIL REDACTED]>
Date: Fri, 17 Nov 2023 11:43:39 +0000
Subject: [PATCH] Add SDL_PIXELFORMAT_INDEX2LSB and SDL_PIXELFORMAT_INDEX2MSB

---
 include/SDL_pixels.h          | 12 +++++++++++-
 src/test/SDL_test_common.c    |  6 ++++++
 src/video/SDL_pixels.c        |  5 +++++
 test/testautomation_pixels.c  |  4 ++++
 test/testautomation_surface.c | 28 ++++++++++++++++++++++++++++
 5 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/include/SDL_pixels.h b/include/SDL_pixels.h
index d6a61297f555..1b2d38a6a960 100644
--- a/include/SDL_pixels.h
+++ b/include/SDL_pixels.h
@@ -61,7 +61,10 @@ typedef enum
     SDL_PIXELTYPE_ARRAYU16,
     SDL_PIXELTYPE_ARRAYU32,
     SDL_PIXELTYPE_ARRAYF16,
-    SDL_PIXELTYPE_ARRAYF32
+    SDL_PIXELTYPE_ARRAYF32,
+
+    /* This must be at the end of the list to avoid breaking the existing ABI */
+    SDL_PIXELTYPE_INDEX2
 } SDL_PixelType;
 
 /** Bitmap pixel order, high bit -> low bit. */
@@ -134,6 +137,7 @@ typedef enum
 #define SDL_ISPIXELFORMAT_INDEXED(format)   \
     (!SDL_ISPIXELFORMAT_FOURCC(format) && \
      ((SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX1) || \
+      (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX2) || \
       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX4) || \
       (SDL_PIXELTYPE(format) == SDL_PIXELTYPE_INDEX8)))
 
@@ -177,6 +181,12 @@ typedef enum
     SDL_PIXELFORMAT_INDEX1MSB =
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX1, SDL_BITMAPORDER_1234, 0,
                                1, 0),
+    SDL_PIXELFORMAT_INDEX2LSB =
+        SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_4321, 0,
+                               2, 0),
+    SDL_PIXELFORMAT_INDEX2MSB =
+        SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX2, SDL_BITMAPORDER_1234, 0,
+                               2, 0),
     SDL_PIXELFORMAT_INDEX4LSB =
         SDL_DEFINE_PIXELFORMAT(SDL_PIXELTYPE_INDEX4, SDL_BITMAPORDER_4321, 0,
                                4, 0),
diff --git a/src/test/SDL_test_common.c b/src/test/SDL_test_common.c
index 9c8163b59060..350887c597fd 100644
--- a/src/test/SDL_test_common.c
+++ b/src/test/SDL_test_common.c
@@ -852,6 +852,12 @@ static void SDLTest_PrintPixelFormat(char *text, size_t maxlen, Uint32 format)
     case SDL_PIXELFORMAT_INDEX1MSB:
         SDL_snprintfcat(text, maxlen, "Index1MSB");
         break;
+    case SDL_PIXELFORMAT_INDEX2LSB:
+        SDL_snprintfcat(text, maxlen, "Index2LSB");
+        break;
+    case SDL_PIXELFORMAT_INDEX2MSB:
+        SDL_snprintfcat(text, maxlen, "Index2MSB");
+        break;
     case SDL_PIXELFORMAT_INDEX4LSB:
         SDL_snprintfcat(text, maxlen, "Index4LSB");
         break;
diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c
index 1167c22d23d5..f67b21cd1896 100644
--- a/src/video/SDL_pixels.c
+++ b/src/video/SDL_pixels.c
@@ -91,6 +91,8 @@ const char *SDL_GetPixelFormatName(Uint32 format)
 
         CASE(SDL_PIXELFORMAT_INDEX1LSB)
         CASE(SDL_PIXELFORMAT_INDEX1MSB)
+        CASE(SDL_PIXELFORMAT_INDEX2LSB)
+        CASE(SDL_PIXELFORMAT_INDEX2MSB)
         CASE(SDL_PIXELFORMAT_INDEX4LSB)
         CASE(SDL_PIXELFORMAT_INDEX4MSB)
         CASE(SDL_PIXELFORMAT_INDEX8)
@@ -299,6 +301,9 @@ Uint32 SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bm
     case 1:
         /* SDL defaults to MSB ordering */
         return SDL_PIXELFORMAT_INDEX1MSB;
+    case 2:
+        /* SDL defaults to MSB ordering */
+        return SDL_PIXELFORMAT_INDEX2MSB;
     case 4:
         /* SDL defaults to MSB ordering */
         return SDL_PIXELFORMAT_INDEX4MSB;
diff --git a/test/testautomation_pixels.c b/test/testautomation_pixels.c
index d5440e5b4db4..12cf632490c7 100644
--- a/test/testautomation_pixels.c
+++ b/test/testautomation_pixels.c
@@ -14,6 +14,8 @@ const int _numRGBPixelFormats = 31;
 Uint32 _RGBPixelFormats[] = {
     SDL_PIXELFORMAT_INDEX1LSB,
     SDL_PIXELFORMAT_INDEX1MSB,
+    SDL_PIXELFORMAT_INDEX2LSB,
+    SDL_PIXELFORMAT_INDEX2MSB,
     SDL_PIXELFORMAT_INDEX4LSB,
     SDL_PIXELFORMAT_INDEX4MSB,
     SDL_PIXELFORMAT_INDEX8,
@@ -47,6 +49,8 @@ Uint32 _RGBPixelFormats[] = {
 const char *_RGBPixelFormatsVerbose[] = {
     "SDL_PIXELFORMAT_INDEX1LSB",
     "SDL_PIXELFORMAT_INDEX1MSB",
+    "SDL_PIXELFORMAT_INDEX2LSB",
+    "SDL_PIXELFORMAT_INDEX2MSB",
     "SDL_PIXELFORMAT_INDEX4LSB",
     "SDL_PIXELFORMAT_INDEX4MSB",
     "SDL_PIXELFORMAT_INDEX8",
diff --git a/test/testautomation_surface.c b/test/testautomation_surface.c
index 41aa24142c0c..c758bdeeac14 100644
--- a/test/testautomation_surface.c
+++ b/test/testautomation_surface.c
@@ -668,6 +668,34 @@ int surface_testOverflow(void *arg)
                         surface != NULL ? "(success)" : SDL_GetError());
     SDL_FreeSurface(surface);
 
+    /* SDL_PIXELFORMAT_INDEX2* needs 1 byte per 4 pixels. */
+    surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 12, 1, 2, 3, SDL_PIXELFORMAT_INDEX2LSB);
+    SDLTest_AssertCheck(surface != NULL, "12px * 2 bits per px fits in 3 bytes: %s",
+                        surface != NULL ? "(success)" : SDL_GetError());
+    SDL_FreeSurface(surface);
+    surface = SDL_CreateRGBSurfaceFrom(buf, 12, 1, 2, 3, 0, 0, 0, 0);
+    SDLTest_AssertCheck(surface != NULL, "12px * 2 bits per px fits in 3 bytes: %s",
+                        surface != NULL ? "(success)" : SDL_GetError());
+    SDL_FreeSurface(surface);
+
+    surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 13, 1, 2, 3, SDL_PIXELFORMAT_INDEX2LSB);
+    SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp (%d)", surface ? surface->pitch : 0);
+    SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0,
+                        "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError());
+    surface = SDL_CreateRGBSurfaceFrom(buf, 13, 1, 2, 3, 0, 0, 0, 0);
+    SDLTest_AssertCheck(surface == NULL, "Should detect pitch < width * bpp");
+    SDLTest_AssertCheck(SDL_strcmp(SDL_GetError(), expectedError) == 0,
+                        "Expected \"%s\", got \"%s\"", expectedError, SDL_GetError());
+
+    surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 13, 1, 2, 4, SDL_PIXELFORMAT_INDEX2LSB);
+    SDLTest_AssertCheck(surface != NULL, "13px * 2 bits per px fits in 4 bytes: %s",
+                        surface != NULL ? "(success)" : SDL_GetError());
+    SDL_FreeSurface(surface);
+    surface = SDL_CreateRGBSurfaceFrom(buf, 13, 1, 2, 4, 0, 0, 0, 0);
+    SDLTest_AssertCheck(surface != NULL, "13px * 2 bits per px fits in 4 bytes: %s",
+                        surface != NULL ? "(success)" : SDL_GetError());
+    SDL_FreeSurface(surface);
+
     /* SDL_PIXELFORMAT_INDEX1* needs 1 byte per 8 pixels. */
     surface = SDL_CreateRGBSurfaceWithFormatFrom(buf, 16, 1, 1, 2, SDL_PIXELFORMAT_INDEX1LSB);
     SDLTest_AssertCheck(surface != NULL, "16px * 1 bit per px fits in 2 bytes: %s",