SDL: Additional colorspace clarification

From db2456038733940fc9d199f1ae800ee7885b63fa Mon Sep 17 00:00:00 2001
From: Sam Lantinga <[EMAIL REDACTED]>
Date: Tue, 5 Mar 2024 16:47:36 -0800
Subject: [PATCH] Additional colorspace clarification

Note that SDL_MATRIX_COEFFICIENTS_BT470BG is functionally equivalent to SDL_MATRIX_COEFFICIENTS_BT601
---
 include/SDL3/SDL_pixels.h             | 60 +++++++++++++--------------
 src/render/metal/SDL_render_metal.m   |  1 +
 src/render/vulkan/SDL_render_vulkan.c |  1 +
 src/video/SDL_pixels.c                |  1 +
 src/video/SDL_yuv.c                   | 18 ++++----
 src/video/yuv2rgb/yuv_rgb_common.h    |  8 ++--
 6 files changed, 46 insertions(+), 43 deletions(-)

diff --git a/include/SDL3/SDL_pixels.h b/include/SDL3/SDL_pixels.h
index 868d1595134c8..d3def2c41bf08 100644
--- a/include/SDL3/SDL_pixels.h
+++ b/include/SDL3/SDL_pixels.h
@@ -471,18 +471,18 @@ typedef enum
 typedef enum
 {
     SDL_COLOR_PRIMARIES_UNKNOWN = 0,
-    SDL_COLOR_PRIMARIES_BT709 = 1,
+    SDL_COLOR_PRIMARIES_BT709 = 1,                  /**< ITU-R BT.709-6 */
     SDL_COLOR_PRIMARIES_UNSPECIFIED = 2,
-    SDL_COLOR_PRIMARIES_BT470M = 4,
-    SDL_COLOR_PRIMARIES_BT470BG = 5,
-    SDL_COLOR_PRIMARIES_BT601 = 6,
-    SDL_COLOR_PRIMARIES_SMPTE240 = 7,
-    SDL_COLOR_PRIMARIES_GENERIC_FILM = 8,
-    SDL_COLOR_PRIMARIES_BT2020 = 9,
-    SDL_COLOR_PRIMARIES_XYZ = 10,
-    SDL_COLOR_PRIMARIES_SMPTE431 = 11,
-    SDL_COLOR_PRIMARIES_SMPTE432 = 12, /* DCI P3 */
-    SDL_COLOR_PRIMARIES_EBU3213 = 22,
+    SDL_COLOR_PRIMARIES_BT470M = 4,                 /**< ITU-R BT.470-6 System M */
+    SDL_COLOR_PRIMARIES_BT470BG = 5,                /**< ITU-R BT.470-6 System B, G / ITU-R BT.601-7 625 */
+    SDL_COLOR_PRIMARIES_BT601 = 6,                  /**< ITU-R BT.601-7 525 */
+    SDL_COLOR_PRIMARIES_SMPTE240 = 7,               /**< SMPTE 240M, functionally the same as SDL_COLOR_PRIMARIES_BT601 */
+    SDL_COLOR_PRIMARIES_GENERIC_FILM = 8,           /**< Generic film (color filters using Illuminant C) */
+    SDL_COLOR_PRIMARIES_BT2020 = 9,                 /**< ITU-R BT.2020-2 / ITU-R BT.2100-0 */
+    SDL_COLOR_PRIMARIES_XYZ = 10,                   /**< SMPTE ST 428-1 */
+    SDL_COLOR_PRIMARIES_SMPTE431 = 11,              /**< SMPTE RP 431-2 */
+    SDL_COLOR_PRIMARIES_SMPTE432 = 12,              /**< SMPTE EG 432-1 / DCI P3 */
+    SDL_COLOR_PRIMARIES_EBU3213 = 22,               /**< EBU Tech. 3213-E */
     SDL_COLOR_PRIMARIES_CUSTOM = 31
 } SDL_ColorPrimaries;
 
@@ -492,11 +492,11 @@ typedef enum
 typedef enum
 {
     SDL_TRANSFER_CHARACTERISTICS_UNKNOWN = 0,
-    SDL_TRANSFER_CHARACTERISTICS_BT709 = 1,         /**< ITU-R BT1361 */
+    SDL_TRANSFER_CHARACTERISTICS_BT709 = 1,         /**< Rec. ITU-R BT.709-6 / ITU-R BT1361 */
     SDL_TRANSFER_CHARACTERISTICS_UNSPECIFIED = 2,
-    SDL_TRANSFER_CHARACTERISTICS_GAMMA22 = 4,       /**< ITU-R BT470M / ITU-R BT1700 625 PAL & SECAM */
-    SDL_TRANSFER_CHARACTERISTICS_GAMMA28 = 5,       /**< ITU-R BT470BG */
-    SDL_TRANSFER_CHARACTERISTICS_BT601 = 6,         /**< SMPTE ST 170M */
+    SDL_TRANSFER_CHARACTERISTICS_GAMMA22 = 4,       /**< ITU-R BT.470-6 System M / ITU-R BT1700 625 PAL & SECAM */
+    SDL_TRANSFER_CHARACTERISTICS_GAMMA28 = 5,       /**< ITU-R BT.470-6 System B, G */
+    SDL_TRANSFER_CHARACTERISTICS_BT601 = 6,         /**< SMPTE ST 170M / ITU-R BT.601-7 525 or 625 */
     SDL_TRANSFER_CHARACTERISTICS_SMPTE240 = 7,      /**< SMPTE ST 240M */
     SDL_TRANSFER_CHARACTERISTICS_LINEAR = 8,
     SDL_TRANSFER_CHARACTERISTICS_LOG100 = 9,
@@ -508,7 +508,7 @@ typedef enum
     SDL_TRANSFER_CHARACTERISTICS_BT2020_12BIT = 15, /**< ITU-R BT2020 for 12-bit system */
     SDL_TRANSFER_CHARACTERISTICS_PQ = 16,           /**< SMPTE ST 2084 for 10-, 12-, 14- and 16-bit systems */
     SDL_TRANSFER_CHARACTERISTICS_SMPTE428 = 17,     /**< SMPTE ST 428-1 */
-    SDL_TRANSFER_CHARACTERISTICS_HLG = 18,          /**< ARIB STD-B67, known as "Hybrid log-gamma" */
+    SDL_TRANSFER_CHARACTERISTICS_HLG = 18,          /**< ARIB STD-B67, known as "hybrid log-gamma" (HLG) */
     SDL_TRANSFER_CHARACTERISTICS_CUSTOM = 31
 } SDL_TransferCharacteristics;
 
@@ -518,19 +518,19 @@ typedef enum
 typedef enum
 {
     SDL_MATRIX_COEFFICIENTS_IDENTITY = 0,
-    SDL_MATRIX_COEFFICIENTS_BT709 = 1,
+    SDL_MATRIX_COEFFICIENTS_BT709 = 1,              /**< ITU-R BT.709-6 */
     SDL_MATRIX_COEFFICIENTS_UNSPECIFIED = 2,
-    SDL_MATRIX_COEFFICIENTS_FCC = 4,
-    SDL_MATRIX_COEFFICIENTS_BT470BG = 5,
-    SDL_MATRIX_COEFFICIENTS_BT601 = 6,
-    SDL_MATRIX_COEFFICIENTS_SMPTE240 = 7,
+    SDL_MATRIX_COEFFICIENTS_FCC = 4,                /**< US FCC */
+    SDL_MATRIX_COEFFICIENTS_BT470BG = 5,            /**< ITU-R BT.470-6 System B, G / ITU-R BT.601-7 625, functionally the same as SDL_MATRIX_COEFFICIENTS_BT601 */
+    SDL_MATRIX_COEFFICIENTS_BT601 = 6,              /**< ITU-R BT.601-7 525 */
+    SDL_MATRIX_COEFFICIENTS_SMPTE240 = 7,           /**< SMPTE 240M */
     SDL_MATRIX_COEFFICIENTS_YCGCO = 8,
-    SDL_MATRIX_COEFFICIENTS_BT2020_NCL = 9,
-    SDL_MATRIX_COEFFICIENTS_BT2020_CL = 10,
-    SDL_MATRIX_COEFFICIENTS_SMPTE2085 = 11,
+    SDL_MATRIX_COEFFICIENTS_BT2020_NCL = 9,         /**< ITU-R BT.2020-2 non-constant luminance */
+    SDL_MATRIX_COEFFICIENTS_BT2020_CL = 10,         /**< ITU-R BT.2020-2 constant luminance */
+    SDL_MATRIX_COEFFICIENTS_SMPTE2085 = 11,         /**< SMPTE ST 2085 */
     SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_NCL = 12,
     SDL_MATRIX_COEFFICIENTS_CHROMA_DERIVED_CL = 13,
-    SDL_MATRIX_COEFFICIENTS_ICTCP = 14,
+    SDL_MATRIX_COEFFICIENTS_ICTCP = 14,             /**< ITU-R BT.2100-0 ICTCP */
     SDL_MATRIX_COEFFICIENTS_CUSTOM = 31
 } SDL_MatrixCoefficients;
 
@@ -558,11 +558,11 @@ typedef enum
 #define SDL_COLORSPACETRANSFER(X)   (SDL_TransferCharacteristics)(((X) >> 5) & 0x1F)
 #define SDL_COLORSPACEMATRIX(X)     (SDL_MatrixCoefficients)((X) & 0x1F)
 
-#define SDL_ISCOLORSPACE_YUV_BT601(X)       (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT601 || SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT470BG)
-#define SDL_ISCOLORSPACE_YUV_BT709(X)       (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT709)
-#define SDL_ISCOLORSPACE_YUV_BT2020(X)      (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT2020_NCL)
-#define SDL_ISCOLORSPACE_LIMITED_RANGE(X)   (SDL_COLORSPACERANGE(X) != SDL_COLOR_RANGE_FULL)
-#define SDL_ISCOLORSPACE_FULL_RANGE(X)      (SDL_COLORSPACERANGE(X) == SDL_COLOR_RANGE_FULL)
+#define SDL_ISCOLORSPACE_MATRIX_BT601(X)        (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT601 || SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT470BG)
+#define SDL_ISCOLORSPACE_MATRIX_BT709(X)        (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT709)
+#define SDL_ISCOLORSPACE_MATRIX_BT2020_NCL(X)   (SDL_COLORSPACEMATRIX(X) == SDL_MATRIX_COEFFICIENTS_BT2020_NCL)
+#define SDL_ISCOLORSPACE_LIMITED_RANGE(X)       (SDL_COLORSPACERANGE(X) != SDL_COLOR_RANGE_FULL)
+#define SDL_ISCOLORSPACE_FULL_RANGE(X)          (SDL_COLORSPACERANGE(X) == SDL_COLOR_RANGE_FULL)
 
 typedef enum
 {
diff --git a/src/render/metal/SDL_render_metal.m b/src/render/metal/SDL_render_metal.m
index bf5db74faf528..392e3e8158757 100644
--- a/src/render/metal/SDL_render_metal.m
+++ b/src/render/metal/SDL_render_metal.m
@@ -590,6 +590,7 @@ size_t GetYCbCRtoRGBConversionMatrix(SDL_Colorspace colorspace, int w, int h, in
     const int YUV_SD_THRESHOLD = 576;
 
     switch (SDL_COLORSPACEMATRIX(colorspace)) {
+    case SDL_MATRIX_COEFFICIENTS_BT470BG:
     case SDL_MATRIX_COEFFICIENTS_BT601:
         return GetBT601ConversionMatrix(colorspace);
 
diff --git a/src/render/vulkan/SDL_render_vulkan.c b/src/render/vulkan/SDL_render_vulkan.c
index d495cd5cc6784..078707f70163d 100644
--- a/src/render/vulkan/SDL_render_vulkan.c
+++ b/src/render/vulkan/SDL_render_vulkan.c
@@ -2505,6 +2505,7 @@ static int VULKAN_CreateTexture(SDL_Renderer *renderer, SDL_Texture *texture, SD
         /* Create samplerYcbcrConversion which will be used on the VkImageView and VkSampler */
         samplerYcbcrConversionCreateInfo.format = textureFormat;
         switch (SDL_COLORSPACEMATRIX(texture->colorspace)) {
+        case SDL_MATRIX_COEFFICIENTS_BT470BG:
         case SDL_MATRIX_COEFFICIENTS_BT601:
             samplerYcbcrConversionCreateInfo.ycbcrModel = VK_SAMPLER_YCBCR_MODEL_CONVERSION_YCBCR_601_KHR;
             break;
diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c
index c321d7ce30204..6553914eb4f8a 100644
--- a/src/video/SDL_pixels.c
+++ b/src/video/SDL_pixels.c
@@ -877,6 +877,7 @@ const float *SDL_GetYCbCRtoRGBConversionMatrix(SDL_Colorspace colorspace, int w,
 
     switch (SDL_COLORSPACEMATRIX(colorspace)) {
     case SDL_MATRIX_COEFFICIENTS_BT601:
+    case SDL_MATRIX_COEFFICIENTS_BT470BG:
         return SDL_GetBT601ConversionMatrix(colorspace);
 
     case SDL_MATRIX_COEFFICIENTS_BT709:
diff --git a/src/video/SDL_yuv.c b/src/video/SDL_yuv.c
index 2d1d001b26a53..127bc016612a7 100644
--- a/src/video/SDL_yuv.c
+++ b/src/video/SDL_yuv.c
@@ -161,25 +161,25 @@ int SDL_CalculateYUVSize(Uint32 format, int w, int h, size_t *size, size_t *pitc
 
 static int GetYUVConversionType(SDL_Colorspace colorspace, YCbCrType *yuv_type)
 {
-    if (SDL_ISCOLORSPACE_YUV_BT601(colorspace)) {
+    if (SDL_ISCOLORSPACE_MATRIX_BT601(colorspace)) {
         if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
-            *yuv_type = YCBCR_601;
+            *yuv_type = YCBCR_601_LIMITED;
         } else {
-            *yuv_type = YCBCR_JPEG;
+            *yuv_type = YCBCR_601_FULL;
         }
         return 0;
     }
 
-    if (SDL_ISCOLORSPACE_YUV_BT709(colorspace)) {
+    if (SDL_ISCOLORSPACE_MATRIX_BT709(colorspace)) {
         if (SDL_ISCOLORSPACE_LIMITED_RANGE(colorspace)) {
-            *yuv_type = YCBCR_709;
+            *yuv_type = YCBCR_709_LIMITED;
             return 0;
         }
     }
 
-    if (SDL_ISCOLORSPACE_YUV_BT2020(colorspace)) {
+    if (SDL_ISCOLORSPACE_MATRIX_BT2020_NCL(colorspace)) {
         if (SDL_ISCOLORSPACE_FULL_RANGE(colorspace)) {
-            *yuv_type = YCBCR_2020;
+            *yuv_type = YCBCR_2020_NCL_FULL;
             return 0;
         }
     }
@@ -593,7 +593,7 @@ int SDL_ConvertPixels_YUV_to_RGB(int width, int height,
     const Uint8 *v = NULL;
     Uint32 y_stride = 0;
     Uint32 uv_stride = 0;
-    YCbCrType yuv_type = YCBCR_601;
+    YCbCrType yuv_type = YCBCR_601_LIMITED;
 
     if (GetYUVPlanes(width, height, src_format, src, src_pitch, &y, &u, &v, &y_stride, &uv_stride) < 0) {
         return -1;
@@ -1121,7 +1121,7 @@ int SDL_ConvertPixels_RGB_to_YUV(int width, int height,
                                  Uint32 src_format, SDL_Colorspace src_colorspace, SDL_PropertiesID src_properties, const void *src, int src_pitch,
                                  Uint32 dst_format, SDL_Colorspace dst_colorspace, SDL_PropertiesID dst_properties, void *dst, int dst_pitch)
 {
-    YCbCrType yuv_type = YCBCR_601;
+    YCbCrType yuv_type = YCBCR_601_LIMITED;
 
     if (GetYUVConversionType(dst_colorspace, &yuv_type) < 0) {
         return -1;
diff --git a/src/video/yuv2rgb/yuv_rgb_common.h b/src/video/yuv2rgb/yuv_rgb_common.h
index 1ab607d015282..774292b0cd0fd 100644
--- a/src/video/yuv2rgb/yuv_rgb_common.h
+++ b/src/video/yuv2rgb/yuv_rgb_common.h
@@ -5,10 +5,10 @@
 
 typedef enum
 {
-    YCBCR_JPEG,
-    YCBCR_601,
-    YCBCR_709,
-    YCBCR_2020
+    YCBCR_601_FULL,
+    YCBCR_601_LIMITED,
+    YCBCR_709_LIMITED,
+    YCBCR_2020_NCL_FULL,
 } YCbCrType;
 
 #endif /* YUV_RGB_COMMON_H_ */