diff options
author | Daniel Stone <daniels@collabora.com> | 2024-06-06 17:26:07 +0100 |
---|---|---|
committer | Marge Bot <emma+marge@anholt.net> | 2024-07-19 13:50:42 +0000 |
commit | 974d31dba70ceea0fa5f1b52bba6e5b6f4abe70f (patch) | |
tree | 4da1a849643e3c0c34da1a6f8e88703b2e860c2c /src/util | |
parent | e05415a82e63bd96473171bf816175b3b190645c (diff) |
format: Generate sRGB<->linear conversions from table
Instead of having a hardcoded table to convert between sRGB formats and
their linear-gamma equivalents (and vice-versa), generate this from the
information in the format table.
This requires adding a 'sublayout' attribute to differentiate between,
e.g. DXT1 and DXT3, which otherwise appear to be equivalent but for
their name prefix.
As an anonymous union is being used, we also need named initialisers for
the util_format_description entries.
Signed-off-by: Daniel Stone <daniels@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29649>
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/format/u_format.h | 214 | ||||
-rw-r--r-- | src/util/format/u_format.yaml | 20 | ||||
-rw-r--r-- | src/util/format/u_format_parse.py | 49 | ||||
-rw-r--r-- | src/util/format/u_format_table.py | 32 |
4 files changed, 101 insertions, 214 deletions
diff --git a/src/util/format/u_format.h b/src/util/format/u_format.h index 126e26091f1..a9c87beb143 100644 --- a/src/util/format/u_format.h +++ b/src/util/format/u_format.h @@ -237,6 +237,15 @@ struct util_format_description * Colorspace transformation. */ enum util_format_colorspace colorspace; + + /** + * For sRGB formats, equivalent linear format; for linear formats, + * equivalent sRGB format + */ + union { + enum pipe_format srgb_equivalent; + enum pipe_format linear_equivalent; + }; }; struct util_format_pack_description { @@ -1059,107 +1068,7 @@ util_format_srgb(enum pipe_format format) if (util_format_is_srgb(format)) return format; - switch (format) { - case PIPE_FORMAT_L8_UNORM: - return PIPE_FORMAT_L8_SRGB; - case PIPE_FORMAT_R8_UNORM: - return PIPE_FORMAT_R8_SRGB; - case PIPE_FORMAT_L8A8_UNORM: - return PIPE_FORMAT_L8A8_SRGB; - case PIPE_FORMAT_R8G8_UNORM: - return PIPE_FORMAT_R8G8_SRGB; - case PIPE_FORMAT_R8G8B8_UNORM: - return PIPE_FORMAT_R8G8B8_SRGB; - case PIPE_FORMAT_B8G8R8_UNORM: - return PIPE_FORMAT_B8G8R8_SRGB; - case PIPE_FORMAT_A8B8G8R8_UNORM: - return PIPE_FORMAT_A8B8G8R8_SRGB; - case PIPE_FORMAT_X8B8G8R8_UNORM: - return PIPE_FORMAT_X8B8G8R8_SRGB; - case PIPE_FORMAT_B8G8R8A8_UNORM: - return PIPE_FORMAT_B8G8R8A8_SRGB; - case PIPE_FORMAT_B8G8R8X8_UNORM: - return PIPE_FORMAT_B8G8R8X8_SRGB; - case PIPE_FORMAT_A8R8G8B8_UNORM: - return PIPE_FORMAT_A8R8G8B8_SRGB; - case PIPE_FORMAT_X8R8G8B8_UNORM: - return PIPE_FORMAT_X8R8G8B8_SRGB; - case PIPE_FORMAT_R8G8B8A8_UNORM: - return PIPE_FORMAT_R8G8B8A8_SRGB; - case PIPE_FORMAT_R8G8B8X8_UNORM: - return PIPE_FORMAT_R8G8B8X8_SRGB; - case PIPE_FORMAT_DXT1_RGB: - return PIPE_FORMAT_DXT1_SRGB; - case PIPE_FORMAT_DXT1_RGBA: - return PIPE_FORMAT_DXT1_SRGBA; - case PIPE_FORMAT_DXT3_RGBA: - return PIPE_FORMAT_DXT3_SRGBA; - case PIPE_FORMAT_DXT5_RGBA: - return PIPE_FORMAT_DXT5_SRGBA; - case PIPE_FORMAT_R5G6B5_UNORM: - return PIPE_FORMAT_R5G6B5_SRGB; - case PIPE_FORMAT_B5G6R5_UNORM: - return PIPE_FORMAT_B5G6R5_SRGB; - case PIPE_FORMAT_BPTC_RGBA_UNORM: - return PIPE_FORMAT_BPTC_SRGBA; - case PIPE_FORMAT_ETC2_RGB8: - return PIPE_FORMAT_ETC2_SRGB8; - case PIPE_FORMAT_ETC2_RGB8A1: - return PIPE_FORMAT_ETC2_SRGB8A1; - case PIPE_FORMAT_ETC2_RGBA8: - return PIPE_FORMAT_ETC2_SRGBA8; - case PIPE_FORMAT_ASTC_4x4: - return PIPE_FORMAT_ASTC_4x4_SRGB; - case PIPE_FORMAT_ASTC_5x4: - return PIPE_FORMAT_ASTC_5x4_SRGB; - case PIPE_FORMAT_ASTC_5x5: - return PIPE_FORMAT_ASTC_5x5_SRGB; - case PIPE_FORMAT_ASTC_6x5: - return PIPE_FORMAT_ASTC_6x5_SRGB; - case PIPE_FORMAT_ASTC_6x6: - return PIPE_FORMAT_ASTC_6x6_SRGB; - case PIPE_FORMAT_ASTC_8x5: - return PIPE_FORMAT_ASTC_8x5_SRGB; - case PIPE_FORMAT_ASTC_8x6: - return PIPE_FORMAT_ASTC_8x6_SRGB; - case PIPE_FORMAT_ASTC_8x8: - return PIPE_FORMAT_ASTC_8x8_SRGB; - case PIPE_FORMAT_ASTC_10x5: - return PIPE_FORMAT_ASTC_10x5_SRGB; - case PIPE_FORMAT_ASTC_10x6: - return PIPE_FORMAT_ASTC_10x6_SRGB; - case PIPE_FORMAT_ASTC_10x8: - return PIPE_FORMAT_ASTC_10x8_SRGB; - case PIPE_FORMAT_ASTC_10x10: - return PIPE_FORMAT_ASTC_10x10_SRGB; - case PIPE_FORMAT_ASTC_12x10: - return PIPE_FORMAT_ASTC_12x10_SRGB; - case PIPE_FORMAT_ASTC_12x12: - return PIPE_FORMAT_ASTC_12x12_SRGB; - case PIPE_FORMAT_ASTC_3x3x3: - return PIPE_FORMAT_ASTC_3x3x3_SRGB; - case PIPE_FORMAT_ASTC_4x3x3: - return PIPE_FORMAT_ASTC_4x3x3_SRGB; - case PIPE_FORMAT_ASTC_4x4x3: - return PIPE_FORMAT_ASTC_4x4x3_SRGB; - case PIPE_FORMAT_ASTC_4x4x4: - return PIPE_FORMAT_ASTC_4x4x4_SRGB; - case PIPE_FORMAT_ASTC_5x4x4: - return PIPE_FORMAT_ASTC_5x4x4_SRGB; - case PIPE_FORMAT_ASTC_5x5x4: - return PIPE_FORMAT_ASTC_5x5x4_SRGB; - case PIPE_FORMAT_ASTC_5x5x5: - return PIPE_FORMAT_ASTC_5x5x5_SRGB; - case PIPE_FORMAT_ASTC_6x5x5: - return PIPE_FORMAT_ASTC_6x5x5_SRGB; - case PIPE_FORMAT_ASTC_6x6x5: - return PIPE_FORMAT_ASTC_6x6x5_SRGB; - case PIPE_FORMAT_ASTC_6x6x6: - return PIPE_FORMAT_ASTC_6x6x6_SRGB; - - default: - return PIPE_FORMAT_NONE; - } + return util_format_description(format)->srgb_equivalent; } /** @@ -1169,107 +1078,10 @@ util_format_srgb(enum pipe_format format) static inline enum pipe_format util_format_linear(enum pipe_format format) { - switch (format) { - case PIPE_FORMAT_L8_SRGB: - return PIPE_FORMAT_L8_UNORM; - case PIPE_FORMAT_R8_SRGB: - return PIPE_FORMAT_R8_UNORM; - case PIPE_FORMAT_L8A8_SRGB: - return PIPE_FORMAT_L8A8_UNORM; - case PIPE_FORMAT_R8G8_SRGB: - return PIPE_FORMAT_R8G8_UNORM; - case PIPE_FORMAT_R8G8B8_SRGB: - return PIPE_FORMAT_R8G8B8_UNORM; - case PIPE_FORMAT_B8G8R8_SRGB: - return PIPE_FORMAT_B8G8R8_UNORM; - case PIPE_FORMAT_A8B8G8R8_SRGB: - return PIPE_FORMAT_A8B8G8R8_UNORM; - case PIPE_FORMAT_X8B8G8R8_SRGB: - return PIPE_FORMAT_X8B8G8R8_UNORM; - case PIPE_FORMAT_B8G8R8A8_SRGB: - return PIPE_FORMAT_B8G8R8A8_UNORM; - case PIPE_FORMAT_B8G8R8X8_SRGB: - return PIPE_FORMAT_B8G8R8X8_UNORM; - case PIPE_FORMAT_A8R8G8B8_SRGB: - return PIPE_FORMAT_A8R8G8B8_UNORM; - case PIPE_FORMAT_X8R8G8B8_SRGB: - return PIPE_FORMAT_X8R8G8B8_UNORM; - case PIPE_FORMAT_R8G8B8A8_SRGB: - return PIPE_FORMAT_R8G8B8A8_UNORM; - case PIPE_FORMAT_R8G8B8X8_SRGB: - return PIPE_FORMAT_R8G8B8X8_UNORM; - case PIPE_FORMAT_DXT1_SRGB: - return PIPE_FORMAT_DXT1_RGB; - case PIPE_FORMAT_DXT1_SRGBA: - return PIPE_FORMAT_DXT1_RGBA; - case PIPE_FORMAT_DXT3_SRGBA: - return PIPE_FORMAT_DXT3_RGBA; - case PIPE_FORMAT_DXT5_SRGBA: - return PIPE_FORMAT_DXT5_RGBA; - case PIPE_FORMAT_R5G6B5_SRGB: - return PIPE_FORMAT_R5G6B5_UNORM; - case PIPE_FORMAT_B5G6R5_SRGB: - return PIPE_FORMAT_B5G6R5_UNORM; - case PIPE_FORMAT_BPTC_SRGBA: - return PIPE_FORMAT_BPTC_RGBA_UNORM; - case PIPE_FORMAT_ETC2_SRGB8: - return PIPE_FORMAT_ETC2_RGB8; - case PIPE_FORMAT_ETC2_SRGB8A1: - return PIPE_FORMAT_ETC2_RGB8A1; - case PIPE_FORMAT_ETC2_SRGBA8: - return PIPE_FORMAT_ETC2_RGBA8; - case PIPE_FORMAT_ASTC_4x4_SRGB: - return PIPE_FORMAT_ASTC_4x4; - case PIPE_FORMAT_ASTC_5x4_SRGB: - return PIPE_FORMAT_ASTC_5x4; - case PIPE_FORMAT_ASTC_5x5_SRGB: - return PIPE_FORMAT_ASTC_5x5; - case PIPE_FORMAT_ASTC_6x5_SRGB: - return PIPE_FORMAT_ASTC_6x5; - case PIPE_FORMAT_ASTC_6x6_SRGB: - return PIPE_FORMAT_ASTC_6x6; - case PIPE_FORMAT_ASTC_8x5_SRGB: - return PIPE_FORMAT_ASTC_8x5; - case PIPE_FORMAT_ASTC_8x6_SRGB: - return PIPE_FORMAT_ASTC_8x6; - case PIPE_FORMAT_ASTC_8x8_SRGB: - return PIPE_FORMAT_ASTC_8x8; - case PIPE_FORMAT_ASTC_10x5_SRGB: - return PIPE_FORMAT_ASTC_10x5; - case PIPE_FORMAT_ASTC_10x6_SRGB: - return PIPE_FORMAT_ASTC_10x6; - case PIPE_FORMAT_ASTC_10x8_SRGB: - return PIPE_FORMAT_ASTC_10x8; - case PIPE_FORMAT_ASTC_10x10_SRGB: - return PIPE_FORMAT_ASTC_10x10; - case PIPE_FORMAT_ASTC_12x10_SRGB: - return PIPE_FORMAT_ASTC_12x10; - case PIPE_FORMAT_ASTC_12x12_SRGB: - return PIPE_FORMAT_ASTC_12x12; - case PIPE_FORMAT_ASTC_3x3x3_SRGB: - return PIPE_FORMAT_ASTC_3x3x3; - case PIPE_FORMAT_ASTC_4x3x3_SRGB: - return PIPE_FORMAT_ASTC_4x3x3; - case PIPE_FORMAT_ASTC_4x4x3_SRGB: - return PIPE_FORMAT_ASTC_4x4x3; - case PIPE_FORMAT_ASTC_4x4x4_SRGB: - return PIPE_FORMAT_ASTC_4x4x4; - case PIPE_FORMAT_ASTC_5x4x4_SRGB: - return PIPE_FORMAT_ASTC_5x4x4; - case PIPE_FORMAT_ASTC_5x5x4_SRGB: - return PIPE_FORMAT_ASTC_5x5x4; - case PIPE_FORMAT_ASTC_5x5x5_SRGB: - return PIPE_FORMAT_ASTC_5x5x5; - case PIPE_FORMAT_ASTC_6x5x5_SRGB: - return PIPE_FORMAT_ASTC_6x5x5; - case PIPE_FORMAT_ASTC_6x6x5_SRGB: - return PIPE_FORMAT_ASTC_6x6x5; - case PIPE_FORMAT_ASTC_6x6x6_SRGB: - return PIPE_FORMAT_ASTC_6x6x6; - default: - assert(!util_format_is_srgb(format)); + if (!util_format_is_srgb(format)) return format; - } + + return util_format_description(format)->linear_equivalent; } /** diff --git a/src/util/format/u_format.yaml b/src/util/format/u_format.yaml index fc0aa0ceb47..f14d6190e2f 100644 --- a/src/util/format/u_format.yaml +++ b/src/util/format/u_format.yaml @@ -7,6 +7,7 @@ # Each format entry contains: # - name, per enum pipe_format # - layout, per enum util_format_layout, in shortened lower caps +# - sublayout, to distinguish between meaningfully-different layout variants # - pixel block's width # - pixel block's height # - pixel block's depth, in number of pixels @@ -815,48 +816,56 @@ # - http://msdn.microsoft.com/en-us/library/bb694531.aspx - name: DXT1_RGB layout: s3tc + sublayout: dxt1 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, 1] - name: DXT1_RGBA layout: s3tc + sublayout: dxt1 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, W] - name: DXT3_RGBA layout: s3tc + sublayout: dxt3 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X128] swizzles: [X, Y, Z, W] - name: DXT5_RGBA layout: s3tc + sublayout: dxt5 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X128] swizzles: [X, Y, Z, W] - name: DXT1_SRGB layout: s3tc + sublayout: dxt1 colorspace: SRGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, 1] - name: DXT1_SRGBA layout: s3tc + sublayout: dxt1 colorspace: SRGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, W] - name: DXT3_SRGBA layout: s3tc + sublayout: dxt3 colorspace: SRGB block: {width: 4, height: 4, depth: 1} channels: [X128] swizzles: [X, Y, Z, W] - name: DXT5_SRGBA layout: s3tc + sublayout: dxt5 colorspace: SRGB block: {width: 4, height: 4, depth: 1} channels: [X128] @@ -932,6 +941,7 @@ - name: ETC1_RGB8 layout: etc + sublayout: etc1 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X64] @@ -939,60 +949,70 @@ - name: ETC2_RGB8 layout: etc + sublayout: etc2 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, 1] - name: ETC2_SRGB8 layout: etc + sublayout: etc2 colorspace: SRGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, 1] - name: ETC2_RGB8A1 layout: etc + sublayout: etc2 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, W] - name: ETC2_SRGB8A1 layout: etc + sublayout: etc2 colorspace: SRGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, Y, Z, W] - name: ETC2_RGBA8 layout: etc + sublayout: etc2 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X128] swizzles: [X, Y, Z, W] - name: ETC2_SRGBA8 layout: etc + sublayout: etc2 colorspace: SRGB block: {width: 4, height: 4, depth: 1} channels: [X128] swizzles: [X, Y, Z, W] - name: ETC2_R11_UNORM layout: etc + sublayout: etc2 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, 0, 0, 1] - name: ETC2_R11_SNORM layout: etc + sublayout: etc2 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X64] swizzles: [X, 0, 0, 1] - name: ETC2_RG11_UNORM layout: etc + sublayout: etc2 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X128] swizzles: [X, Y, 0, 1] - name: ETC2_RG11_SNORM layout: etc + sublayout: etc2 colorspace: RGB block: {width: 4, height: 4, depth: 1} channels: [X128] diff --git a/src/util/format/u_format_parse.py b/src/util/format/u_format_parse.py index 0170d26583b..274dbad2ad2 100644 --- a/src/util/format/u_format_parse.py +++ b/src/util/format/u_format_parse.py @@ -225,11 +225,17 @@ class Format: self.name = "unknown" self.name = f"PIPE_FORMAT_{consume_str(self, source, 'name')}" self.layout = consume_str(self, source, 'layout') + if 'sublayout' in source: + self.sublayout = consume_str(self, source, 'sublayout') + else: + self.sublayout = None self.block_width = consume_int(self, source, 'block', 'width') self.block_height = consume_int(self, source, 'block', 'height') self.block_depth = consume_int(self, source, 'block', 'depth') consumed(self, source, 'block') self.colorspace = consume_str(self, source, 'colorspace') + self.srgb_equivalent = None + self.linear_equivalent = None # Formats with no endian-dependent swizzling declare their channel and # swizzle layout at the top level. Else they can declare an @@ -323,6 +329,8 @@ class Format: return self.name def __eq__(self, other): + if not other: + return False return self.name == other.name def __hash__(self): @@ -523,6 +531,27 @@ def _parse_channels(fields, layout, colorspace, swizzles): return channels +def mostly_equivalent(one, two): + if one.layout != two.layout or \ + one.sublayout != two.sublayout or \ + one.block_width != two.block_width or \ + one.block_height != two.block_height or \ + one.block_depth != two.block_depth or \ + one.le_swizzles != two.le_swizzles or \ + one.le_channels != two.le_channels or \ + one.be_swizzles != two.be_swizzles or \ + one.be_channels != two.be_channels: + return False + return True + +def should_ignore_for_mapping(fmt): + # This format is a really special reinterpretation of depth/stencil as + # RGB. Until we figure out something better, just special-case it so + # we won't consider it as equivalent to anything. + if fmt.name == "PIPE_FORMAT_Z24_UNORM_S8_UINT_AS_R8G8B8A8": + return True + return False + def parse(filename): '''Parse the format description in YAML format in terms of the @@ -543,4 +572,24 @@ def parse(filename): raise RuntimeError(f"Duplicate format entry {f.name}") ret.append(f) + for fmt in ret: + if should_ignore_for_mapping(fmt): + continue + if fmt.colorspace != RGB and fmt.colorspace != SRGB: + continue + if fmt.colorspace == RGB: + for equiv in ret: + if equiv.colorspace != SRGB or not mostly_equivalent(fmt, equiv) or \ + should_ignore_for_mapping(equiv): + continue + assert(fmt.srgb_equivalent == None) + fmt.srgb_equivalent = equiv + elif fmt.colorspace == SRGB: + for equiv in ret: + if equiv.colorspace != RGB or not mostly_equivalent(fmt, equiv) or \ + should_ignore_for_mapping(equiv): + continue + assert(fmt.linear_equivalent == None) + fmt.linear_equivalent = equiv + return ret diff --git a/src/util/format/u_format_table.py b/src/util/format/u_format_table.py index 76d020a2383..1228b5190ae 100644 --- a/src/util/format/u_format_table.py +++ b/src/util/format/u_format_table.py @@ -41,7 +41,6 @@ def layout_map(layout): def colorspace_map(colorspace): return 'UTIL_FORMAT_COLORSPACE_' + str(colorspace).upper() - colorspace_channels_map = { 'RGB': ['r', 'g', 'b', 'a'], 'SRGB': ['sr', 'sg', 'sb', 'a'], @@ -150,6 +149,7 @@ def write_format_aliases(formats): print("#define %s %s" % (f.be_alias, f.name), file=sys.stdout3) print("#endif", file=sys.stdout3) + def write_format_table(formats): write_format_table_header(sys.stdout) print('#include "util/format/u_format.h"') @@ -245,20 +245,26 @@ def write_format_table(formats): sn = format.short_name() print(" [%s] = {" % (format.name,)) - print(" %s," % (format.name,)) - print(" \"%s\"," % (format.name,)) - print(" \"%s\"," % (sn,)) - print(" {%u, %u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_depth, format.block_size())) - print(" %s," % (layout_map(format.layout),)) - print(" %u,\t/* nr_channels */" % (format.nr_channels(),)) - print(" %s,\t/* is_array */" % (bool_map(format.is_array()),)) - print(" %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),)) - print(" %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),)) - print(" %s,\t/* is_unorm */" % (bool_map(format.is_unorm()),)) - print(" %s,\t/* is_snorm */" % (bool_map(format.is_snorm()),)) + print(" .format = %s," % (format.name,)) + print(" .name = \"%s\"," % (format.name,)) + print(" .short_name = \"%s\"," % (sn,)) + print(" .block = {%u, %u, %u, %u},\t/* block */" % (format.block_width, format.block_height, format.block_depth, format.block_size())) + print(" .layout = %s," % (layout_map(format.layout),)) + print(" .nr_channels = %u,\t/* nr_channels */" % (format.nr_channels(),)) + print(" .is_array = %s,\t/* is_array */" % (bool_map(format.is_array()),)) + print(" .is_bitmask = %s,\t/* is_bitmask */" % (bool_map(format.is_bitmask()),)) + print(" .is_mixed = %s,\t/* is_mixed */" % (bool_map(format.is_mixed()),)) + print(" .is_unorm = %s,\t/* is_unorm */" % (bool_map(format.is_unorm()),)) + print(" .is_snorm = %s,\t/* is_snorm */" % (bool_map(format.is_snorm()),)) u_format_pack.print_channels(format, do_channel_array) u_format_pack.print_channels(format, do_swizzle_array) - print(" %s," % (colorspace_map(format.colorspace),)) + print(" .colorspace = %s," % (colorspace_map(format.colorspace),)) + if format.srgb_equivalent: + print(" .srgb_equivalent = %s,\t/* srgb_equivalent */" % format.srgb_equivalent.name) + elif format.linear_equivalent: + print(" .linear_equivalent = %s,\t/* linear_equivalent */" % format.linear_equivalent.name) + else: + print(" .srgb_equivalent = PIPE_FORMAT_NONE,\t/* srgb_equivalent */") print(" },") print() print("};") |