[Mesa-dev] [PATCH 09/20] mesa: Add a concept of an array format
From: Jason Ekstrand jason.ekstr...@intel.com An array format is a 32-bit integer format identifier that can represent any format that can be represented as an array of standard GL datatypes. While the MESA_FORMAT enums provide several of these, they don't account for all of them. v2 by Iago Toral Quiroga ito...@igalia.com: - Set pad to 0 and array_format_bit to 1 for all mesa array formats. - Fix array_format_flip_channels, since it was not doing what was expected. --- src/mesa/main/format_info.py | 41 src/mesa/main/formats.c | 56 +++- src/mesa/main/formats.h | 55 +++ 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/mesa/main/format_info.py b/src/mesa/main/format_info.py index 7424fe0..315767d 100644 --- a/src/mesa/main/format_info.py +++ b/src/mesa/main/format_info.py @@ -98,6 +98,32 @@ def get_gl_data_type(fmat): else: assert False +def get_array_format_datatype(chan): + if chan.type == parser.FLOAT: + if chan.size == 16: + return 'MESA_ARRAY_FORMAT_TYPE_HALF' + elif chan.size == 32: + return 'MESA_ARRAY_FORMAT_TYPE_FLOAT' + else: + assert False + elif chan.type in (parser.SIGNED, parser.UNSIGNED): + datatype = 'MESA_ARRAY_FORMAT_TYPE_' + if chan.type == parser.UNSIGNED: + datatype += 'U' + + if chan.size == 8: + datatype += 'BYTE' + elif chan.size == 16: + datatype += 'SHORT' + elif chan.size == 32: + datatype += 'INT' + else: + print chan.size + assert False + return datatype + else: + assert False + def get_mesa_layout(fmat): if fmat.layout == 'array': return 'MESA_FORMAT_LAYOUT_ARRAY' @@ -192,6 +218,21 @@ for fmat in formats: int(fmat.block_size() / 8)) print ' {{ {0} }},'.format(', '.join(map(str, fmat.swizzle))) + if fmat.is_array() and fmat.colorspace in ('rgb', 'srgb'): + chan = fmat.array_element() + print ' {0} ,'.format(', '.join([ + get_array_format_datatype(chan), + str(int(chan.norm)), + str(len(fmat.channels)), + str(fmat.swizzle[0]), + str(fmat.swizzle[1]), + str(fmat.swizzle[2]), + str(fmat.swizzle[3]), + str(int(0)), + str(int(1)) + ])) + else: + print ' {{ MESA_ARRAY_FORMAT_TYPE_UBYTE, 0, 0, 0, 0, 0, 0, 0, 0 }},' print ' },' print '};' diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index 7ec0507..f86925e 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -71,6 +71,7 @@ struct gl_format_info GLubyte BytesPerBlock; uint8_t Swizzle[4]; + mesa_array_format ArrayFormat; }; #include format_info.c @@ -269,6 +270,60 @@ _mesa_get_format_swizzle(mesa_format format, uint8_t swizzle_out[4]) memcpy(swizzle_out, info-Swizzle, sizeof(info-Swizzle)); } +static mesa_array_format +array_format_flip_channels(mesa_array_format format) +{ + if (format.num_channels == 1) + return format; + + if (format.num_channels == 2) { + int tmp = format.swizzle_x; + format.swizzle_x = format.swizzle_y; + format.swizzle_y = tmp; + return format; + } + + if (format.num_channels == 4) { + int tmp = format.swizzle_x; + format.swizzle_x = format.swizzle_w; + format.swizzle_w = tmp; + tmp = format.swizzle_y; + format.swizzle_y = format.swizzle_z; + format.swizzle_z = tmp; + return format; + } + + assert(!Invalid array format); +} + +uint32_t +_mesa_format_to_array_format(mesa_format format) +{ + const struct gl_format_info *info = _mesa_get_format_info(format); + if (_mesa_little_endian()) + return info-ArrayFormat.as_uint; + else + return array_format_flip_channels(info-ArrayFormat).as_uint; +} + +mesa_format +_mesa_format_from_array_format(uint32_t array_format) +{ + mesa_array_format af; + unsigned f; + + af.as_uint = array_format; + af.pad = 0; + if (!_mesa_little_endian()) + af = array_format_flip_channels(af); + + assert(af.array_format_bit); + for (f = 1; f MESA_FORMAT_COUNT; ++f) + if (_mesa_get_format_info(f)-ArrayFormat.as_uint == af.as_uint) + return f; + + return MESA_FORMAT_NONE; +} /** Is the given format a compressed format? */ GLboolean @@ -278,7 +333,6 @@ _mesa_is_format_compressed(mesa_format format) return info-BlockWidth 1 || info-BlockHeight 1; } - /** * Determine if the given format represents a packed depth/stencil buffer. */ diff --git a/src/mesa/main/formats.h b/src/mesa/main/formats.h index 213ab56..7642875 100644 --- a/src/mesa/main/formats.h +++ b/src/mesa/main/formats.h @@ -81,6 +81,55 @@ enum { MESA_FORMAT_SWIZZLE_NONE = 6, }; +enum mesa_array_format_datatype { + MESA_ARRAY_FORMAT_TYPE_UBYTE = 0x0, +
Re: [Mesa-dev] [PATCH 09/20] mesa: Add a concept of an array format
On Tue, Nov 18, 2014 at 12:43 AM, Iago Toral Quiroga ito...@igalia.com wrote: From: Jason Ekstrand jason.ekstr...@intel.com An array format is a 32-bit integer format identifier that can represent any format that can be represented as an array of standard GL datatypes. While the MESA_FORMAT enums provide several of these, they don't account for all of them. v2 by Iago Toral Quiroga ito...@igalia.com: - Set pad to 0 and array_format_bit to 1 for all mesa array formats. - Fix array_format_flip_channels, since it was not doing what was expected. I'm not terribly surprised, I never got a chance to test that function before I handed it off to you. I'm curious how you found it though, given that it's only run on big endian architectures. Maybe it was just obviously wrong. (silly me). In any case, the new version looks good to me. --Jason --- src/mesa/main/format_info.py | 41 src/mesa/main/formats.c | 56 +++- src/mesa/main/formats.h | 55 +++ 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/mesa/main/format_info.py b/src/mesa/main/format_info.py index 7424fe0..315767d 100644 --- a/src/mesa/main/format_info.py +++ b/src/mesa/main/format_info.py @@ -98,6 +98,32 @@ def get_gl_data_type(fmat): else: assert False +def get_array_format_datatype(chan): + if chan.type == parser.FLOAT: + if chan.size == 16: + return 'MESA_ARRAY_FORMAT_TYPE_HALF' + elif chan.size == 32: + return 'MESA_ARRAY_FORMAT_TYPE_FLOAT' + else: + assert False + elif chan.type in (parser.SIGNED, parser.UNSIGNED): + datatype = 'MESA_ARRAY_FORMAT_TYPE_' + if chan.type == parser.UNSIGNED: + datatype += 'U' + + if chan.size == 8: + datatype += 'BYTE' + elif chan.size == 16: + datatype += 'SHORT' + elif chan.size == 32: + datatype += 'INT' + else: + print chan.size + assert False + return datatype + else: + assert False + def get_mesa_layout(fmat): if fmat.layout == 'array': return 'MESA_FORMAT_LAYOUT_ARRAY' @@ -192,6 +218,21 @@ for fmat in formats: int(fmat.block_size() / 8)) print ' {{ {0} }},'.format(', '.join(map(str, fmat.swizzle))) + if fmat.is_array() and fmat.colorspace in ('rgb', 'srgb'): + chan = fmat.array_element() + print ' {0} ,'.format(', '.join([ + get_array_format_datatype(chan), + str(int(chan.norm)), + str(len(fmat.channels)), + str(fmat.swizzle[0]), + str(fmat.swizzle[1]), + str(fmat.swizzle[2]), + str(fmat.swizzle[3]), + str(int(0)), + str(int(1)) + ])) + else: + print ' {{ MESA_ARRAY_FORMAT_TYPE_UBYTE, 0, 0, 0, 0, 0, 0, 0, 0 }},' print ' },' print '};' diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index 7ec0507..f86925e 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -71,6 +71,7 @@ struct gl_format_info GLubyte BytesPerBlock; uint8_t Swizzle[4]; + mesa_array_format ArrayFormat; }; #include format_info.c @@ -269,6 +270,60 @@ _mesa_get_format_swizzle(mesa_format format, uint8_t swizzle_out[4]) memcpy(swizzle_out, info-Swizzle, sizeof(info-Swizzle)); } +static mesa_array_format +array_format_flip_channels(mesa_array_format format) +{ + if (format.num_channels == 1) + return format; + + if (format.num_channels == 2) { + int tmp = format.swizzle_x; + format.swizzle_x = format.swizzle_y; + format.swizzle_y = tmp; + return format; + } + + if (format.num_channels == 4) { + int tmp = format.swizzle_x; + format.swizzle_x = format.swizzle_w; + format.swizzle_w = tmp; + tmp = format.swizzle_y; + format.swizzle_y = format.swizzle_z; + format.swizzle_z = tmp; + return format; + } + + assert(!Invalid array format); +} + +uint32_t +_mesa_format_to_array_format(mesa_format format) +{ + const struct gl_format_info *info = _mesa_get_format_info(format); + if (_mesa_little_endian()) + return info-ArrayFormat.as_uint; + else + return array_format_flip_channels(info-ArrayFormat).as_uint; +} + +mesa_format +_mesa_format_from_array_format(uint32_t array_format) +{ + mesa_array_format af; + unsigned f; + + af.as_uint = array_format; + af.pad = 0; + if (!_mesa_little_endian()) + af = array_format_flip_channels(af); + + assert(af.array_format_bit); + for (f = 1; f MESA_FORMAT_COUNT; ++f) + if (_mesa_get_format_info(f)-ArrayFormat.as_uint == af.as_uint) + return f; + + return MESA_FORMAT_NONE; +} /** Is the given format a compressed format? */ GLboolean @@ -278,7
Re: [Mesa-dev] [PATCH 09/20] mesa: Add a concept of an array format
On Tue, 2014-11-18 at 10:46 -0800, Jason Ekstrand wrote: On Tue, Nov 18, 2014 at 12:43 AM, Iago Toral Quiroga ito...@igalia.com wrote: From: Jason Ekstrand jason.ekstr...@intel.com An array format is a 32-bit integer format identifier that can represent any format that can be represented as an array of standard GL datatypes. While the MESA_FORMAT enums provide several of these, they don't account for all of them. v2 by Iago Toral Quiroga ito...@igalia.com: - Set pad to 0 and array_format_bit to 1 for all mesa array formats. - Fix array_format_flip_channels, since it was not doing what was expected. I'm not terribly surprised, I never got a chance to test that function before I handed it off to you. I'm curious how you found it though, given that it's only run on big endian architectures. Maybe it was just obviously wrong. (silly me). In any case, the new version looks good to me. I noticed that because at some point I thought I needed to flip the channels for GL_UNSIGNED_INT_8_8_8_8 in certain cases (I was wrong about that in the end, but that drove me to look into it), and when I looked at the function it was pretty obvious that it was not doing what it was expected. Iago --Jason --- src/mesa/main/format_info.py | 41 src/mesa/main/formats.c | 56 +++- src/mesa/main/formats.h | 55 +++ 3 files changed, 151 insertions(+), 1 deletion(-) diff --git a/src/mesa/main/format_info.py b/src/mesa/main/format_info.py index 7424fe0..315767d 100644 --- a/src/mesa/main/format_info.py +++ b/src/mesa/main/format_info.py @@ -98,6 +98,32 @@ def get_gl_data_type(fmat): else: assert False +def get_array_format_datatype(chan): + if chan.type == parser.FLOAT: + if chan.size == 16: + return 'MESA_ARRAY_FORMAT_TYPE_HALF' + elif chan.size == 32: + return 'MESA_ARRAY_FORMAT_TYPE_FLOAT' + else: + assert False + elif chan.type in (parser.SIGNED, parser.UNSIGNED): + datatype = 'MESA_ARRAY_FORMAT_TYPE_' + if chan.type == parser.UNSIGNED: + datatype += 'U' + + if chan.size == 8: + datatype += 'BYTE' + elif chan.size == 16: + datatype += 'SHORT' + elif chan.size == 32: + datatype += 'INT' + else: + print chan.size + assert False + return datatype + else: + assert False + def get_mesa_layout(fmat): if fmat.layout == 'array': return 'MESA_FORMAT_LAYOUT_ARRAY' @@ -192,6 +218,21 @@ for fmat in formats: int(fmat.block_size() / 8)) print ' {{ {0} }},'.format(', '.join(map(str, fmat.swizzle))) + if fmat.is_array() and fmat.colorspace in ('rgb', 'srgb'): + chan = fmat.array_element() + print ' {0} ,'.format(', '.join([ + get_array_format_datatype(chan), + str(int(chan.norm)), + str(len(fmat.channels)), + str(fmat.swizzle[0]), + str(fmat.swizzle[1]), + str(fmat.swizzle[2]), + str(fmat.swizzle[3]), + str(int(0)), + str(int(1)) + ])) + else: + print ' {{ MESA_ARRAY_FORMAT_TYPE_UBYTE, 0, 0, 0, 0, 0, 0, 0, 0 }},' print ' },' print '};' diff --git a/src/mesa/main/formats.c b/src/mesa/main/formats.c index 7ec0507..f86925e 100644 --- a/src/mesa/main/formats.c +++ b/src/mesa/main/formats.c @@ -71,6 +71,7 @@ struct gl_format_info GLubyte BytesPerBlock; uint8_t Swizzle[4]; + mesa_array_format ArrayFormat; }; #include format_info.c @@ -269,6 +270,60 @@ _mesa_get_format_swizzle(mesa_format format, uint8_t swizzle_out[4]) memcpy(swizzle_out, info-Swizzle, sizeof(info-Swizzle)); } +static mesa_array_format +array_format_flip_channels(mesa_array_format format) +{ + if (format.num_channels == 1) + return format; + + if (format.num_channels == 2) { + int tmp = format.swizzle_x; +