]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
drm: drm_fourcc: add 10/12/16bit software decoder YCbCr formats
authorRobert Mader <robert.mader@collabora.com>
Fri, 9 May 2025 13:35:35 +0000 (15:35 +0200)
committerDaniel Stone <daniels@collabora.com>
Thu, 29 May 2025 15:32:58 +0000 (16:32 +0100)
This adds FOURCCs for 3-plane 10/12/16bit YCbCr formats used by software
decoders like ffmpeg, dav1d and libvpx. The intended use-case is buffer
sharing between decoders and GPUs by allocating buffers with e.g. udmabuf
or dma-heaps, avoiding unnecessary copies and format conversions in
various scenarios.

Unlike formats typically used by hardware decoders the 10/12bit formats
use a LSB alignment. In order to allow fast implementations in GL
and Vulkan the padding must contain only zeros, so the float
representation can be calculated by multiplying with 2^6=64 or 2^4=16
respectively.

MRs or branches for Mesa, Vulkan, Gstreamer, Weston and Mutter can be found at:
 - https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/34303
 - https://github.com/rmader/Vulkan-Docs/commits/ycbcr-16bit-lsb-formats/
 - https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/8540
 - https://gitlab.freedesktop.org/wayland/weston/-/merge_requests/1753
 - https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/4348

The naming scheme follows the 'P' and 'Q' formats. The 'S' stands for
'software' and was selected in order to make remembering easy.

The 'Sx16' formats could as well be 'Qx16'. We stick with 'S' as 16bit software
decoders are likely much more common than hardware ones for the foreseeable
future. Note that these formats already have Vulkan equivalents:
 - VK_FORMAT_G16_B16_R16_3PLANE_420_UNORM
 - VK_FORMAT_G16_B16_R16_3PLANE_422_UNORM
 - VK_FORMAT_G16_B16_R16_3PLANE_444_UNORM

Signed-off-by: Robert Mader <robert.mader@collabora.com>
Reviewed-by: Daniel Stone <daniels@collabora.com>
Link: https://lore.kernel.org/r/20250509133535.60330-1-robert.mader@collabora.com
Signed-off-by: Daniel Stone <daniels@collabora.com>
drivers/gpu/drm/drm_fourcc.c
include/uapi/drm/drm_fourcc.h

index 3a94ca211f9ce9637d3690d4b03ddc414ee5a6d4..55ddd99fd7f6a8e050e00ca5f97de689d69ebf2d 100644 (file)
@@ -346,6 +346,33 @@ const struct drm_format_info *__drm_format_info(u32 format)
                { .format = DRM_FORMAT_P030,            .depth = 0,  .num_planes = 2,
                  .char_per_block = { 4, 8, 0 }, .block_w = { 3, 3, 0 }, .block_h = { 1, 1, 0 },
                  .hsub = 2, .vsub = 2, .is_yuv = true},
+               { .format = DRM_FORMAT_S010,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 2, .vsub = 2, .is_yuv = true},
+               { .format = DRM_FORMAT_S210,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 2, .vsub = 1, .is_yuv = true},
+               { .format = DRM_FORMAT_S410,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 1, .vsub = 1, .is_yuv = true},
+               { .format = DRM_FORMAT_S012,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 2, .vsub = 2, .is_yuv = true},
+               { .format = DRM_FORMAT_S212,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 2, .vsub = 1, .is_yuv = true},
+               { .format = DRM_FORMAT_S412,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 1, .vsub = 1, .is_yuv = true},
+               { .format = DRM_FORMAT_S016,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 2, .vsub = 2, .is_yuv = true},
+               { .format = DRM_FORMAT_S216,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 2, .vsub = 1, .is_yuv = true},
+               { .format = DRM_FORMAT_S416,            .depth = 0,  .num_planes = 3,
+                 .char_per_block = { 2, 2, 2 }, .block_w = { 1, 1, 1 }, .block_h = { 1, 1, 1 },
+                 .hsub = 1, .vsub = 1, .is_yuv = true},
        };
 
        unsigned int i;
index 81202a50dc9e2e4363abba91ca164b30d5b2f71d..6483f76a2165b25b806e596fc6c1ffa20131e47a 100644 (file)
@@ -377,6 +377,42 @@ extern "C" {
  */
 #define DRM_FORMAT_Q401                fourcc_code('Q', '4', '0', '1')
 
+/*
+ * 3 plane YCbCr LSB aligned
+ * In order to use these formats in a similar fashion to MSB aligned ones
+ * implementation can multiply the values by 2^6=64. For that reason the padding
+ * must only contain zeros.
+ * index 0 = Y plane, [15:0] z:Y [6:10] little endian
+ * index 1 = Cr plane, [15:0] z:Cr [6:10] little endian
+ * index 2 = Cb plane, [15:0] z:Cb [6:10] little endian
+ */
+#define DRM_FORMAT_S010        fourcc_code('S', '0', '1', '0') /* 2x2 subsampled Cb (1) and Cr (2) planes 10 bits per channel */
+#define DRM_FORMAT_S210        fourcc_code('S', '2', '1', '0') /* 2x1 subsampled Cb (1) and Cr (2) planes 10 bits per channel */
+#define DRM_FORMAT_S410        fourcc_code('S', '4', '1', '0') /* non-subsampled Cb (1) and Cr (2) planes 10 bits per channel */
+
+/*
+ * 3 plane YCbCr LSB aligned
+ * In order to use these formats in a similar fashion to MSB aligned ones
+ * implementation can multiply the values by 2^4=16. For that reason the padding
+ * must only contain zeros.
+ * index 0 = Y plane, [15:0] z:Y [4:12] little endian
+ * index 1 = Cr plane, [15:0] z:Cr [4:12] little endian
+ * index 2 = Cb plane, [15:0] z:Cb [4:12] little endian
+ */
+#define DRM_FORMAT_S012        fourcc_code('S', '0', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes 12 bits per channel */
+#define DRM_FORMAT_S212        fourcc_code('S', '2', '1', '2') /* 2x1 subsampled Cb (1) and Cr (2) planes 12 bits per channel */
+#define DRM_FORMAT_S412        fourcc_code('S', '4', '1', '2') /* non-subsampled Cb (1) and Cr (2) planes 12 bits per channel */
+
+/*
+ * 3 plane YCbCr
+ * index 0 = Y plane, [15:0] Y little endian
+ * index 1 = Cr plane, [15:0] Cr little endian
+ * index 2 = Cb plane, [15:0] Cb little endian
+ */
+#define DRM_FORMAT_S016        fourcc_code('S', '0', '1', '6') /* 2x2 subsampled Cb (1) and Cr (2) planes 16 bits per channel */
+#define DRM_FORMAT_S216        fourcc_code('S', '2', '1', '6') /* 2x1 subsampled Cb (1) and Cr (2) planes 16 bits per channel */
+#define DRM_FORMAT_S416        fourcc_code('S', '4', '1', '6') /* non-subsampled Cb (1) and Cr (2) planes 16 bits per channel */
+
 /*
  * 3 plane YCbCr
  * index 0: Y plane, [7:0] Y