gallium: Fix big-endian addressing of non-bitmask array formats.
authorEric Anholt <eric@anholt.net>
Thu, 15 Aug 2019 22:38:00 +0000 (15:38 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 28 Aug 2019 17:39:36 +0000 (10:39 -0700)
The formats affected are:

- LA x (16_FLOAT, 32_FLOAT, 32_UINT, 32_SINT)
- R8G8B8 x (UNORM, SNORM, SRGB, USCALED, SSCALED, UINT, SINT)
- RG/RGB/RGBA x (64_FLOAT, 32_FLOAT, 16_FLOAT, 32_UNORM, 32_SNORM,
                 32_USCALED, 32_SSCALED, 32_FIXED, 32_UINT, 32_SINT)
- RGB/RGBA x (16_UNORM, 16_SNORM, 16_USCALED, 16_SSCALED,
              16_UINT, 16_SINT)
- RGBx16 x (UNORM, SNORM, FLOAT, UINT, SINT)
- RGBx32 x (FLOAT, UINT, SINT)
- RA x (16_FLOAT, 32_FLOAT, 32_UINT, 32_SINT)

The updated st_formats.c unit test checks that the formats affected by
this change are all array formats in the equivalent Mesa format (if
any).  Mesa's array format definition is clear: the value stored is an
array (increasing memory address) of values of the channel's type.
It's also the only thing that makes sense for the RGB types, or very
large types like RGBA64_FLOAT (A should not move to the low address
because the cpu is BE).

Acked-by: Roland Scheidegger <sroland@vmware.com>
Acked-by: Adam Jackson <ajax@redhat.com>
Tested-by: Matt Turner <mattst88@gmail.com> (unit tests on BE)
Reviewed-by: Marek Olšák <marek.olsak@amd.com>
src/gallium/auxiliary/util/u_format_parse.py
src/mesa/state_tracker/tests/st_format.c

index b9627055cda3f5277bddc1936614a983f1359d00..541ae69d4dc662e16c08ed7c27a9e65534a4b08f 100644 (file)
@@ -379,16 +379,27 @@ def parse(filename):
             channel.shift = le_shift
             le_shift += channel.size
 
-        be_shift = 0
-        for channel in be_channels[3::-1]:
-            channel.shift = be_shift
-            be_shift += channel.size
-
-        assert le_shift == be_shift
         for i in range(4):
             assert (le_swizzles[i] != SWIZZLE_NONE) == (be_swizzles[i] != SWIZZLE_NONE)
 
         format = Format(name, layout, block_width, block_height, block_depth, le_channels, le_swizzles, be_channels, be_swizzles, colorspace)
+
+        if format.is_array() and not format.is_bitmask():
+            # Formats accessed as arrays by the pack functions (R32G32_FLOAT or
+            # R8G8B8_UNORM, for example) should not be channel-ordering-reversed
+            # for BE.
+            # Note that __eq__ on channels ignores .shift!
+            assert(format.be_channels == format.le_channels)
+            assert(format.be_swizzles == format.le_swizzles)
+            format.be_channels = format.le_channels
+        else:
+            be_shift = 0
+            for channel in format.be_channels[3::-1]:
+                channel.shift = be_shift
+                be_shift += channel.size
+
+            assert le_shift == be_shift
+
         formats.append(format)
     return formats
 
index 12cb74bd0be34ca83276c16ff1f74f2ca4b32445..e42a1873d5ed383ed5bd6b91c21e6e2b4e7c20ac 100644 (file)
@@ -87,6 +87,29 @@ int main(int argc, char **argv)
          continue;
 
       if (mf != MESA_FORMAT_NONE) {
+         const struct util_format_description *desc = util_format_description(i);
+
+         /* Make sure that gallium and Mesa agree on whether the format is an
+          * array format.
+          */
+         if (desc->nr_channels > 1) {
+            bool mesa_array = (_mesa_get_format_layout(mf) ==
+                               MESA_FORMAT_LAYOUT_ARRAY);
+            bool gallium_array = desc->is_array && !desc->is_bitmask;
+            /* We should probably be checking equality here, but we have some
+             * UINT and SINT types that are array formats in Mesa but not in
+             * gallium.
+             */
+            if (gallium_array && !mesa_array) {
+               fprintf(stderr, "%s is %sarray, %s is %sarray\n",
+                       util_format_short_name(i),
+                       gallium_array ? "" : "not ",
+                       _mesa_get_format_name(mf),
+                       mesa_array ? "" : "not ");
+               return 1;
+            }
+         }
+
          enum pipe_format pf =
             st_mesa_format_to_pipe_format(st, mf);
          if (pf != i) {