From 5e01ec4bd0ac07685d5759868130e7c13f0125f3 Mon Sep 17 00:00:00 2001 From: Boris Brezillon Date: Tue, 27 May 2025 09:23:26 +0200 Subject: [PATCH] util/format: Auto-generate a bunch of YUV helpers Now that the YUV subsampling pattern is encoded in the name, we can auto-generate a bunch of helpers that were previously hand-written, and are pretty often lagging behind when new formats are added. Signed-off-by: Boris Brezillon Part-of: --- src/util/format/u_format.h | 127 ------------------- src/util/format/u_format_table.py | 197 +++++++++++++++++++++++++++++- src/util/format/u_formats.h | 54 -------- 3 files changed, 196 insertions(+), 182 deletions(-) diff --git a/src/util/format/u_format.h b/src/util/format/u_format.h index 95b2b574063..a1bef3192e6 100644 --- a/src/util/format/u_format.h +++ b/src/util/format/u_format.h @@ -1301,133 +1301,6 @@ util_format_get_num_planes(enum pipe_format format) } } -static inline enum pipe_format -util_format_get_plane_format(enum pipe_format format, unsigned plane) -{ - switch (format) { - case PIPE_FORMAT_YV12: - case PIPE_FORMAT_YV16: - case PIPE_FORMAT_IYUV: - case PIPE_FORMAT_Y8_U8_V8_422_UNORM: - case PIPE_FORMAT_Y8_U8_V8_444_UNORM: - case PIPE_FORMAT_Y8_400_UNORM: - case PIPE_FORMAT_R8_G8_B8_UNORM: - case PIPE_FORMAT_Y8_U8_V8_440_UNORM: - return PIPE_FORMAT_R8_UNORM; - case PIPE_FORMAT_NV12: - case PIPE_FORMAT_NV16: - case PIPE_FORMAT_R8_G8B8_420_UNORM: - case PIPE_FORMAT_R8_G8B8_422_UNORM: - return !plane ? PIPE_FORMAT_R8_UNORM : PIPE_FORMAT_RG88_UNORM; - case PIPE_FORMAT_NV21: - case PIPE_FORMAT_R8_B8G8_420_UNORM: - case PIPE_FORMAT_R8_B8G8_422_UNORM: - return !plane ? PIPE_FORMAT_R8_UNORM : PIPE_FORMAT_GR88_UNORM; - case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: - case PIPE_FORMAT_Y16_U16_V16_420_UNORM: - case PIPE_FORMAT_Y16_U16_V16_422_UNORM: - case PIPE_FORMAT_Y16_U16_V16_444_UNORM: - return PIPE_FORMAT_R16_UNORM; - case PIPE_FORMAT_P010: - case PIPE_FORMAT_P012: - case PIPE_FORMAT_P016: - case PIPE_FORMAT_P030: - case PIPE_FORMAT_Y16_U16V16_422_UNORM: - return !plane ? PIPE_FORMAT_R16_UNORM : PIPE_FORMAT_R16G16_UNORM; - default: - return format; - } -} - -static inline unsigned -util_format_get_plane_width(enum pipe_format format, unsigned plane, - unsigned width) -{ - switch (format) { - case PIPE_FORMAT_YV12: - case PIPE_FORMAT_YV16: - case PIPE_FORMAT_IYUV: - case PIPE_FORMAT_NV12: - case PIPE_FORMAT_NV21: - case PIPE_FORMAT_P010: - case PIPE_FORMAT_P012: - case PIPE_FORMAT_P016: - case PIPE_FORMAT_P030: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: - case PIPE_FORMAT_Y16_U16_V16_420_UNORM: - case PIPE_FORMAT_Y16_U16_V16_422_UNORM: - case PIPE_FORMAT_Y16_U16_V16_444_UNORM: - case PIPE_FORMAT_Y8_U8_V8_422_UNORM: - case PIPE_FORMAT_NV16: - case PIPE_FORMAT_Y16_U16V16_422_UNORM: - case PIPE_FORMAT_R8_G8B8_420_UNORM: - case PIPE_FORMAT_R8_B8G8_420_UNORM: - case PIPE_FORMAT_G8_B8R8_420_UNORM: - case PIPE_FORMAT_R8_G8B8_422_UNORM: - case PIPE_FORMAT_R8_B8G8_422_UNORM: - case PIPE_FORMAT_G8_B8R8_422_UNORM: - case PIPE_FORMAT_R8_G8_B8_420_UNORM: - case PIPE_FORMAT_R8_B8_G8_420_UNORM: - case PIPE_FORMAT_G8_B8_R8_420_UNORM: - case PIPE_FORMAT_R10_G10B10_420_UNORM: - case PIPE_FORMAT_R10_G10B10_422_UNORM: - case PIPE_FORMAT_X6G10_X6B10X6R10_420_UNORM: - case PIPE_FORMAT_X4G12_X4B12X4R12_420_UNORM: - return !plane ? width : (width + 1) / 2; - default: - return width; - } -} - -static inline unsigned -util_format_get_plane_height(enum pipe_format format, unsigned plane, - unsigned height) -{ - switch (format) { - case PIPE_FORMAT_YV12: - case PIPE_FORMAT_IYUV: - case PIPE_FORMAT_NV12: - case PIPE_FORMAT_NV21: - case PIPE_FORMAT_P010: - case PIPE_FORMAT_P012: - case PIPE_FORMAT_P016: - case PIPE_FORMAT_P030: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: - case PIPE_FORMAT_Y16_U16_V16_420_UNORM: - case PIPE_FORMAT_Y16_U16_V16_422_UNORM: - case PIPE_FORMAT_Y16_U16_V16_444_UNORM: - case PIPE_FORMAT_Y8_U8_V8_440_UNORM: - case PIPE_FORMAT_R8_G8B8_420_UNORM: - case PIPE_FORMAT_R8_B8G8_420_UNORM: - case PIPE_FORMAT_G8_B8R8_420_UNORM: - case PIPE_FORMAT_R8_G8_B8_420_UNORM: - case PIPE_FORMAT_R8_B8_G8_420_UNORM: - case PIPE_FORMAT_G8_B8_R8_420_UNORM: - case PIPE_FORMAT_R10_G10B10_420_UNORM: - case PIPE_FORMAT_X6G10_X6B10X6R10_420_UNORM: - case PIPE_FORMAT_X4G12_X4B12X4R12_420_UNORM: - return !plane ? height : (height + 1) / 2; - case PIPE_FORMAT_YV16: - default: - return height; - } -} - /** * Return the number of components stored. * Formats with block size != 1x1 will always have 1 component (the block). diff --git a/src/util/format/u_format_table.py b/src/util/format/u_format_table.py index 4644fc6794d..9488a6c9164 100644 --- a/src/util/format/u_format_table.py +++ b/src/util/format/u_format_table.py @@ -294,6 +294,195 @@ def write_format_aliases(formats): print("#define %s %s" % (f.be_alias, f.name), file=sys.stdout3) print("#endif", file=sys.stdout3) +CHROMA_SUBSAMP = ['400', '420', '422', '444', '440'] + +def write_to_chroma_format(formats): + print('enum pipe_video_chroma_format {', file=sys.stdout3) + for subsamp in CHROMA_SUBSAMP: + print(' PIPE_VIDEO_CHROMA_FORMAT_%s,' % subsamp, file=sys.stdout3) + print(' PIPE_VIDEO_CHROMA_FORMAT_NONE,', file=sys.stdout3) + print('};', file=sys.stdout3) + print(file=sys.stdout3) + print('static inline enum pipe_video_chroma_format', file=sys.stdout3) + print('pipe_format_to_chroma_format(enum pipe_format format)', file=sys.stdout3) + print('{', file=sys.stdout3) + print(' switch(format) {', file=sys.stdout3) + for subsamp in CHROMA_SUBSAMP: + format_count = 0 + for f in formats: + if f.colorspace == 'YUV': + yuv_split_name = f.name.split('_') + if yuv_split_name[-2] == subsamp: + print(' case %s:' % f.name, file=sys.stdout3) + format_count += 1 + if format_count > 0: + print(' return PIPE_VIDEO_CHROMA_FORMAT_%s;' % subsamp, file=sys.stdout3) + print(' default:', file=sys.stdout3) + print(' return PIPE_VIDEO_CHROMA_FORMAT_NONE;', file=sys.stdout3) + print(' }', file=sys.stdout3) + print('}', file=sys.stdout3) + +def chroma_horizontal_subsample_factor(subsample_name): + assert(subsample_name in CHROMA_SUBSAMP) + if subsample_name in ['420', '422']: + return 2 + return 1 + +def chroma_vertical_subsample_factor(subsample_name): + assert(subsample_name in CHROMA_SUBSAMP) + if subsample_name in ['420', '440']: + return 2 + return 1 + +def write_get_plane_width_height(formats): + print('static inline unsigned', file=sys.stdout3) + print('util_format_get_plane_width(enum pipe_format format, unsigned plane,', file=sys.stdout3) + print(' unsigned width)', file=sys.stdout3) + print('{', file=sys.stdout3) + print(' if (!plane)', file=sys.stdout3) + print(' return width;', file=sys.stdout3) + print(file=sys.stdout3) + print(' switch (format) {', file=sys.stdout3) + for factor in [2]: + format_count = 0 + for f in formats: + if f.layout in ['planar2', 'planar3']: + split_name = f.name.split('_') + subsamp = split_name[-2] + if subsamp not in CHROMA_SUBSAMP: + continue + if chroma_horizontal_subsample_factor(subsamp) != factor: + continue + print(' case %s:' % f.name, file=sys.stdout3) + format_count += 1 + if format_count > 0: + print(' return DIV_ROUND_UP(width, %d);' % factor, file=sys.stdout3) + print(' default:', file=sys.stdout3) + print(' return width;', file=sys.stdout3) + print(' }', file=sys.stdout3) + print('}', file=sys.stdout3) + print(file=sys.stdout3) + print('static inline unsigned', file=sys.stdout3) + print('util_format_get_plane_height(enum pipe_format format, unsigned plane,', file=sys.stdout3) + print(' unsigned height)', file=sys.stdout3) + print('{', file=sys.stdout3) + print(' if (!plane)', file=sys.stdout3) + print(' return height;', file=sys.stdout3) + print(file=sys.stdout3) + print(' switch (format) {', file=sys.stdout3) + for factor in [2]: + format_count = 0 + for f in formats: + if f.layout in ['planar2', 'planar3']: + split_name = f.name.split('_') + subsamp = split_name[-2] + if subsamp not in CHROMA_SUBSAMP: + continue + if chroma_vertical_subsample_factor(subsamp) != factor: + continue + print(' case %s:' % f.name, file=sys.stdout3) + format_count += 1 + if format_count > 0: + print(' return DIV_ROUND_UP(height, %d);' % factor, file=sys.stdout3) + print(' default:', file=sys.stdout3) + print(' return height;', file=sys.stdout3) + print(' }', file=sys.stdout3) + print('}', file=sys.stdout3) + +def write_get_plane_format(formats): + to_rgb_plane_format = { + 'Y8': 'R8', + 'U8': 'R8', + 'V8': 'R8', + 'X6Y10': 'X6R10', + 'X6U10': 'X6R10', + 'X6V10': 'X6R10', + 'Y10X6': 'R16', + 'U10X6': 'R16', + 'V10X6': 'R16', + 'X6U10X6V10': 'X6R10X6G10', + 'X6V10X6U10': 'X6R10X6G10', + 'X4Y12': 'X4R12', + 'X4U12': 'X4R12', + 'X4V12': 'X4R12', + 'Y12X4': 'R16', + 'U12X4': 'R16', + 'V12X4': 'R16', + 'X4U12X4V12': 'X4R12X4G12', + 'X4V12X4U12': 'X4R12X4G12', + 'Y16': 'R16', + 'U16': 'R16', + 'V16': 'R16', + 'U16V16': 'R16G16', + 'U8V8': 'RG88', + 'V8U8': 'GR88', + 'R8': 'R8', + 'G8': 'R8', + 'B8': 'R8', + 'G8B8': 'RG88', + 'B8G8': 'GR88', + 'B8R8': 'GR88', + 'X6G10': 'X6R10', + 'X6B10X6R10': 'X6R10X6G10', + 'X4G12': 'X4R12', + 'X4B12X4R12': 'X4R12X4G12', + } + + print('static inline enum pipe_format', file=sys.stdout3) + print('util_format_get_plane_format(enum pipe_format format, unsigned plane)', file=sys.stdout3) + print('{', file=sys.stdout3) + print(' switch (format) {', file=sys.stdout3) + unhandled_formats = [] + for f in formats: + if f.layout not in ['planar2', 'planar3']: + continue + nplanes = 3 if f.layout == 'planar3' else 2 + planes = f.short_name().upper().split('_') + assert(planes[-1] == 'UNORM') + planes.pop(-1) + if planes[-1] in CHROMA_SUBSAMP: + planes.pop(-1) + rgb_formats = [None, None, None] + no_match = False + same_format_on_all_planes = True + for i in range(nplanes): + if planes[i] not in to_rgb_plane_format: + no_match = True + break + rgb_formats[i] = to_rgb_plane_format[planes[i]] + if i > 0 and rgb_formats[i] != rgb_formats[i - 1]: + same_format_on_all_planes = False + + if no_match: + unhandled_formats += [f.name] + continue + + print(' case %s:' % f.name, file=sys.stdout3) + if same_format_on_all_planes: + print(' return PIPE_FORMAT_%s_UNORM;' % rgb_formats[0], file=sys.stdout3) + else: + if nplanes == 3: + assert(rgb_formats[1] == rgb_formats[2]) + print(' return !plane ? PIPE_FORMAT_%s_UNORM : PIPE_FORMAT_%s_UNORM;' % (rgb_formats[0], rgb_formats[1]), file=sys.stdout3) + + print(file=sys.stdout3) + if len(unhandled_formats) > 0: + print(' /* No matching per-plane RGB format, we return the original format in that case. */', file=sys.stdout3) + for f in unhandled_formats: + print(' case %s:' % f, file=sys.stdout3) + print(' default:', file=sys.stdout3) + print(' return format;', file=sys.stdout3) + print(' }', file=sys.stdout3) + print('}', file=sys.stdout3) + print(file=sys.stdout3) + +def write_format_inline_helpers(formats): + write_to_chroma_format(formats) + print(file=sys.stdout3) + write_get_plane_format(formats) + print(file=sys.stdout3) + write_get_plane_width_height(formats) + print(file=sys.stdout3) def write_format_table(formats): write_format_table_header(sys.stdout) @@ -323,14 +512,20 @@ def write_format_table(formats): write_format_table_header(sys.stdout3) + print('#include "util/macros.h"', file=sys.stdout3) + print(file=sys.stdout3) + print('#ifdef __cplusplus', file=sys.stdout3) print('extern "C" {', file=sys.stdout3) print('#endif', file=sys.stdout3) print(file=sys.stdout3) write_format_enum(formats) - print('', file=sys.stdout3) + print(file=sys.stdout3) write_format_aliases(formats) + print(file=sys.stdout3) + write_format_inline_helpers(formats) + print(file=sys.stdout3) print('#ifdef __cplusplus', file=sys.stdout3) print('} /* extern "C" */', file=sys.stdout3) diff --git a/src/util/format/u_formats.h b/src/util/format/u_formats.h index 2a075d8c084..ab0583172c9 100644 --- a/src/util/format/u_formats.h +++ b/src/util/format/u_formats.h @@ -36,60 +36,6 @@ extern "C" { #endif -enum pipe_video_chroma_format -{ - PIPE_VIDEO_CHROMA_FORMAT_400, - PIPE_VIDEO_CHROMA_FORMAT_420, - PIPE_VIDEO_CHROMA_FORMAT_422, - PIPE_VIDEO_CHROMA_FORMAT_444, - PIPE_VIDEO_CHROMA_FORMAT_440, - PIPE_VIDEO_CHROMA_FORMAT_NONE -}; - -static inline enum pipe_video_chroma_format -pipe_format_to_chroma_format(enum pipe_format format) -{ - switch (format) { - case PIPE_FORMAT_NV12: - case PIPE_FORMAT_NV21: - case PIPE_FORMAT_YV12: - case PIPE_FORMAT_IYUV: - case PIPE_FORMAT_P010: - case PIPE_FORMAT_P012: - case PIPE_FORMAT_P016: - case PIPE_FORMAT_P030: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_420_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_420_UNORM: - case PIPE_FORMAT_Y16_U16_V16_420_UNORM: - case PIPE_FORMAT_Y8U8V8_420_UNORM_PACKED: - case PIPE_FORMAT_Y10U10V10_420_UNORM_PACKED: - return PIPE_VIDEO_CHROMA_FORMAT_420; - case PIPE_FORMAT_UYVY: - case PIPE_FORMAT_VYUY: - case PIPE_FORMAT_YUYV: - case PIPE_FORMAT_YVYU: - case PIPE_FORMAT_YV16: - case PIPE_FORMAT_NV16: - case PIPE_FORMAT_Y8_U8_V8_422_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_422_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_422_UNORM: - case PIPE_FORMAT_Y16_U16_V16_422_UNORM: - case PIPE_FORMAT_Y16_U16V16_422_UNORM: - return PIPE_VIDEO_CHROMA_FORMAT_422; - case PIPE_FORMAT_Y8_U8_V8_444_UNORM: - case PIPE_FORMAT_Y10X6_U10X6_V10X6_444_UNORM: - case PIPE_FORMAT_Y12X4_U12X4_V12X4_444_UNORM: - case PIPE_FORMAT_Y16_U16_V16_444_UNORM: - return PIPE_VIDEO_CHROMA_FORMAT_444; - case PIPE_FORMAT_Y8_U8_V8_440_UNORM: - return PIPE_VIDEO_CHROMA_FORMAT_440; - case PIPE_FORMAT_Y8_400_UNORM: - return PIPE_VIDEO_CHROMA_FORMAT_400; - default: - return PIPE_VIDEO_CHROMA_FORMAT_NONE; - } -} - /** * Texture & format swizzles */