[Mesa-dev] [PATCH 13/14] gallivm: Fix big-endian machines

Adam Jackson ajax at redhat.com
Tue Jun 18 10:28:14 PDT 2013


From: Richard Sandiford <r.sandiford at uk.ibm.com>

This adds a bit-shift count to the format table, and adds the concept of
vector or bitwise alignment on gathers.

Reviewed-by: Adam Jackson <ajax at redhat.com>
Signed-off-by: Richard Sandiford <r.sandiford at uk.ibm.com>
---
 src/gallium/auxiliary/gallivm/lp_bld_format_aos.c | 22 +++----
 src/gallium/auxiliary/gallivm/lp_bld_format_soa.c | 17 +++--
 src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c |  2 +-
 src/gallium/auxiliary/gallivm/lp_bld_gather.c     | 25 +++++--
 src/gallium/auxiliary/gallivm/lp_bld_gather.h     |  6 +-
 src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c |  4 +-
 src/gallium/auxiliary/gallivm/lp_bld_swizzle.c    | 80 ++++++++++++++++-------
 src/gallium/auxiliary/util/u_format.h             | 25 ++++++-
 src/gallium/auxiliary/util/u_format_pack.py       |  8 +--
 src/gallium/auxiliary/util/u_format_parse.py      | 10 +++
 src/gallium/auxiliary/util/u_format_table.py      |  4 +-
 src/gallium/drivers/llvmpipe/lp_bld_depth.c       | 29 ++------
 12 files changed, 145 insertions(+), 87 deletions(-)

diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
index 3675e68..af755d4 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
@@ -139,12 +139,12 @@ format_matches_type(const struct util_format_description *desc,
 
 
 /**
- * Unpack a single pixel into its RGBA components.
+ * Unpack a single pixel into its XYZW components.
  *
  * @param desc  the pixel format for the packed pixel value
  * @param packed integer pixel in a format such as PIPE_FORMAT_B8G8R8A8_UNORM
  *
- * @return RGBA in a float[4] or ubyte[4] or ushort[4] vector.
+ * @return XYZW in a float[4] or ubyte[4] or ushort[4] vector.
  */
 static INLINE LLVMValueRef
 lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm,
@@ -159,7 +159,6 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm,
 
    boolean normalized;
    boolean needs_uitofp;
-   unsigned shift;
    unsigned i;
 
    /* TODO: Support more formats */
@@ -190,11 +189,11 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm,
    /* Initialize vector constants */
    normalized = FALSE;
    needs_uitofp = FALSE;
-   shift = 0;
 
    /* Loop over 4 color components */
    for (i = 0; i < 4; ++i) {
       unsigned bits = desc->channel[i].size;
+      unsigned shift = desc->channel[i].shift;
 
       if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
          shifts[i] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
@@ -220,12 +219,10 @@ lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm,
          else
             scales[i] =  lp_build_const_float(gallivm, 1.0);
       }
-
-      shift += bits;
    }
 
-   /* Ex: convert packed = {BGRA, BGRA, BGRA, BGRA}
-    * into masked = {B, G, R, A}
+   /* Ex: convert packed = {XYZW, XYZW, XYZW, XYZW}
+    * into masked = {X, Y, Z, W}
     */
    shifted = LLVMBuildLShr(builder, packed, LLVMConstVector(shifts, 4), "");
    masked = LLVMBuildAnd(builder, shifted, LLVMConstVector(masks, 4), "");
@@ -272,7 +269,6 @@ lp_build_pack_rgba_aos(struct gallivm_state *gallivm,
    LLVMValueRef shifts[4];
    LLVMValueRef scales[4];
    boolean normalized;
-   unsigned shift;
    unsigned i, j;
 
    assert(desc->layout == UTIL_FORMAT_LAYOUT_PLAIN);
@@ -298,9 +294,9 @@ lp_build_pack_rgba_aos(struct gallivm_state *gallivm,
                                        LLVMConstVector(swizzles, 4), "");
 
    normalized = FALSE;
-   shift = 0;
    for (i = 0; i < 4; ++i) {
       unsigned bits = desc->channel[i].size;
+      unsigned shift = desc->channel[i].shift;
 
       if (desc->channel[i].type == UTIL_FORMAT_TYPE_VOID) {
          shifts[i] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
@@ -321,8 +317,6 @@ lp_build_pack_rgba_aos(struct gallivm_state *gallivm,
          else
             scales[i] = lp_build_const_float(gallivm, 1.0);
       }
-
-      shift += bits;
    }
 
    if (normalized)
@@ -406,7 +400,7 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
 
       packed = lp_build_gather(gallivm, type.length/4,
                                format_desc->block.bits, type.width*4,
-                               base_ptr, offset);
+                               base_ptr, offset, TRUE);
 
       assert(format_desc->block.bits <= vec_len);
 
@@ -444,7 +438,7 @@ lp_build_fetch_rgba_aos(struct gallivm_state *gallivm,
 
          packed = lp_build_gather_elem(gallivm, num_pixels,
                                        format_desc->block.bits, 32,
-                                       base_ptr, offset, k);
+                                       base_ptr, offset, k, FALSE);
 
          tmps[k] = lp_build_unpack_arith_rgba_aos(gallivm,
                                                   format_desc,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c
index edc2442..a822e1a 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c
@@ -115,7 +115,6 @@ lp_build_unpack_rgba_soa(struct gallivm_state *gallivm,
    LLVMBuilderRef builder = gallivm->builder;
    struct lp_build_context bld;
    LLVMValueRef inputs[4];
-   unsigned start;
    unsigned chan;
 
    assert(format_desc->layout == UTIL_FORMAT_LAYOUT_PLAIN);
@@ -128,9 +127,9 @@ lp_build_unpack_rgba_soa(struct gallivm_state *gallivm,
    lp_build_context_init(&bld, gallivm, type);
 
    /* Decode the input vector components */
-   start = 0;
    for (chan = 0; chan < format_desc->nr_channels; ++chan) {
       const unsigned width = format_desc->channel[chan].size;
+      const unsigned start = format_desc->channel[chan].shift;
       const unsigned stop = start + width;
       LLVMValueRef input;
 
@@ -256,8 +255,6 @@ lp_build_unpack_rgba_soa(struct gallivm_state *gallivm,
       }
 
       inputs[chan] = input;
-
-      start = stop;
    }
 
    lp_build_format_swizzle_soa(format_desc, &bld, inputs, rgba_out);
@@ -360,13 +357,14 @@ lp_build_fetch_rgba_soa(struct gallivm_state *gallivm,
 
       /*
        * gather the texels from the texture
-       * Ex: packed = {BGRA, BGRA, BGRA, BGRA}.
+       * Ex: packed = {XYZW, XYZW, XYZW, XYZW}
        */
+      assert(format_desc->block.bits <= type.width);
       packed = lp_build_gather(gallivm,
                                type.length,
                                format_desc->block.bits,
                                type.width,
-                               base_ptr, offset);
+                               base_ptr, offset, FALSE);
 
       /*
        * convert texels to float rgba
@@ -391,7 +389,8 @@ lp_build_fetch_rgba_soa(struct gallivm_state *gallivm,
 
       packed = lp_build_gather(gallivm, type.length,
                                format_desc->block.bits,
-                               type.width, base_ptr, offset);
+                               type.width, base_ptr, offset,
+			       FALSE);
       if (format_desc->format == PIPE_FORMAT_R11G11B10_FLOAT) {
          lp_build_r11g11b10_to_float(gallivm, packed, rgba_out);
       }
@@ -418,14 +417,14 @@ lp_build_fetch_rgba_soa(struct gallivm_state *gallivm,
          LLVMValueRef s_offset = lp_build_const_int_vec(gallivm, type, 4);
          offset = LLVMBuildAdd(builder, offset, s_offset, "");
          packed = lp_build_gather(gallivm, type.length,
-                                  32, type.width, base_ptr, offset);
+                                  32, type.width, base_ptr, offset, FALSE);
          packed = LLVMBuildAnd(builder, packed,
                                lp_build_const_int_vec(gallivm, type, mask), "");
       }
       else {
          assert (format_desc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT);
          packed = lp_build_gather(gallivm, type.length,
-                                  32, type.width, base_ptr, offset);
+                                  32, type.width, base_ptr, offset, TRUE);
          packed = LLVMBuildBitCast(builder, packed,
                                    lp_build_vec_type(gallivm, type), "");
       }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c
index e542abc..873f354 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c
@@ -497,7 +497,7 @@ lp_build_fetch_subsampled_rgba_aos(struct gallivm_state *gallivm,
    assert(format_desc->block.width == 2);
    assert(format_desc->block.height == 1);
 
-   packed = lp_build_gather(gallivm, n, 32, 32, base_ptr, offset);
+   packed = lp_build_gather(gallivm, n, 32, 32, base_ptr, offset, FALSE);
 
    (void)j;
 
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_gather.c b/src/gallium/auxiliary/gallivm/lp_bld_gather.c
index eefb23a..9155d81 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_gather.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_gather.c
@@ -78,7 +78,8 @@ lp_build_gather_elem(struct gallivm_state *gallivm,
                      unsigned dst_width,
                      LLVMValueRef base_ptr,
                      LLVMValueRef offsets,
-                     unsigned i)
+                     unsigned i,
+                     boolean vector_justify)
 {
    LLVMTypeRef src_type = LLVMIntTypeInContext(gallivm->context, src_width);
    LLVMTypeRef src_ptr_type = LLVMPointerType(src_type, 0);
@@ -97,10 +98,12 @@ lp_build_gather_elem(struct gallivm_state *gallivm,
       res = LLVMBuildTrunc(gallivm->builder, res, dst_elem_type, "");
    } else if (src_width < dst_width) {
       res = LLVMBuildZExt(gallivm->builder, res, dst_elem_type, "");
+      if (vector_justify) {
 #ifdef PIPE_ARCH_BIG_ENDIAN
-      res = LLVMBuildShl(gallivm->builder, res,
-                         LLVMConstInt(dst_elem_type, dst_width - src_width, 0), "");
+         res = LLVMBuildShl(gallivm->builder, res,
+                            LLVMConstInt(dst_elem_type, dst_width - src_width, 0), "");
 #endif
+      }
    }
 
    return res;
@@ -112,11 +115,20 @@ lp_build_gather_elem(struct gallivm_state *gallivm,
  * Use for fetching texels from a texture.
  * For SSE, typical values are length=4, src_width=32, dst_width=32.
  *
+ * When src_width < dst_width, the return value can be justified in
+ * one of two ways:
+ * "integer justification" is used when the caller treats the destination
+ * as a packed integer bitmask, as described by the channels' "shift" and
+ * "width" fields;
+ * "vector justification" is used when the caller casts the destination
+ * to a vector and needs channel X to be in vector element 0.
+ *
  * @param length length of the offsets
  * @param src_width src element width in bits
  * @param dst_width result element width in bits (src will be expanded to fit)
  * @param base_ptr base pointer, should be a i8 pointer type.
  * @param offsets vector with offsets
+ * @param vector_justify select vector rather than integer justification
  */
 LLVMValueRef
 lp_build_gather(struct gallivm_state *gallivm,
@@ -124,7 +136,8 @@ lp_build_gather(struct gallivm_state *gallivm,
                 unsigned src_width,
                 unsigned dst_width,
                 LLVMValueRef base_ptr,
-                LLVMValueRef offsets)
+                LLVMValueRef offsets,
+                boolean vector_justify)
 {
    LLVMValueRef res;
 
@@ -132,7 +145,7 @@ lp_build_gather(struct gallivm_state *gallivm,
       /* Scalar */
       return lp_build_gather_elem(gallivm, length,
                                   src_width, dst_width,
-                                  base_ptr, offsets, 0);
+                                  base_ptr, offsets, 0, vector_justify);
    } else {
       /* Vector */
 
@@ -146,7 +159,7 @@ lp_build_gather(struct gallivm_state *gallivm,
          LLVMValueRef elem;
          elem = lp_build_gather_elem(gallivm, length,
                                      src_width, dst_width,
-                                     base_ptr, offsets, i);
+                                     base_ptr, offsets, i, vector_justify);
          res = LLVMBuildInsertElement(gallivm->builder, res, elem, index, "");
       }
    }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_gather.h b/src/gallium/auxiliary/gallivm/lp_bld_gather.h
index 8e4c07d..ee69473 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_gather.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_gather.h
@@ -47,7 +47,8 @@ lp_build_gather_elem(struct gallivm_state *gallivm,
                      unsigned dst_width,
                      LLVMValueRef base_ptr,
                      LLVMValueRef offsets,
-                     unsigned i);
+                     unsigned i,
+                     boolean vector_justify);
 
 LLVMValueRef
 lp_build_gather(struct gallivm_state *gallivm,
@@ -55,7 +56,8 @@ lp_build_gather(struct gallivm_state *gallivm,
                 unsigned src_width,
                 unsigned dst_width,
                 LLVMValueRef base_ptr,
-                LLVMValueRef offsets);
+                LLVMValueRef offsets,
+                boolean vector_justify);
 
 LLVMValueRef
 lp_build_gather_values(struct gallivm_state * gallivm,
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
index c31b05d..104c24d 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c
@@ -531,7 +531,7 @@ lp_build_sample_fetch_image_nearest(struct lp_build_sample_context *bld,
                               bld->texel_type.length,
                               bld->format_desc->block.bits,
                               bld->texel_type.width,
-                              data_ptr, offset);
+                              data_ptr, offset, TRUE);
 
       rgba8 = LLVMBuildBitCast(builder, rgba8, u8n_vec_type, "");
    }
@@ -893,7 +893,7 @@ lp_build_sample_fetch_image_linear(struct lp_build_sample_context *bld,
                                        bld->texel_type.length,
                                        bld->format_desc->block.bits,
                                        bld->texel_type.width,
-                                       data_ptr, offset[k][j][i]);
+                                       data_ptr, offset[k][j][i], TRUE);
 
                rgba8 = LLVMBuildBitCast(builder, rgba8, u8n_vec_type, "");
             }
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c
index 08d817a..79116bc 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_swizzle.c
@@ -217,6 +217,20 @@ lp_build_swizzle_scalar_aos(struct lp_build_context *bld,
 
       a = LLVMBuildBitCast(builder, a, lp_build_vec_type(bld->gallivm, type2), "");
 
+      /*
+       * Vector element 0 is always channel X.
+       *
+       *                        76 54 32 10 (array numbering)
+       * Little endian reg in:  YX YX YX YX
+       * Little endian reg out: YY YY YY YY if shift right (shift == -1)
+       *                        XX XX XX XX if shift left (shift == 1)
+       *
+       *                        01 23 45 67 (array numbering)
+       * Big endian reg in:     XY XY XY XY
+       * Big endian reg out:    YY YY YY YY if shift left (shift == 1)
+       *                        XX XX XX XX if shift right (shift == -1)
+       *
+       */
 #ifdef PIPE_ARCH_LITTLE_ENDIAN
       shift = channel == 0 ? 1 : -1;
 #else
@@ -240,10 +254,23 @@ lp_build_swizzle_scalar_aos(struct lp_build_context *bld,
       /*
        * Bit mask and recursive shifts
        *
+       * Little-endian registers:
+       *
+       *   7654 3210
+       *   WZYX WZYX .... WZYX  <= input
+       *   00Y0 00Y0 .... 00Y0  <= mask
+       *   00YY 00YY .... 00YY  <= shift right 1 (shift amount -1)
+       *   YYYY YYYY .... YYYY  <= shift left 2 (shift amount 2)
+       *
+       * Big-endian registers:
+       *
+       *   0123 4567
        *   XYZW XYZW .... XYZW  <= input
-       *   0Y00 0Y00 .... 0Y00
-       *   YY00 YY00 .... YY00
-       *   YYYY YYYY .... YYYY  <= output
+       *   0Y00 0Y00 .... 0Y00  <= mask
+       *   YY00 YY00 .... YY00  <= shift left 1 (shift amount 1)
+       *   YYYY YYYY .... YYYY  <= shift right 2 (shift amount -2)
+       *
+       * shifts[] gives little-endian shift amounts; we need to negate for big-endian.
        */
       struct lp_type type4;
       const int shifts[4][2] = {
@@ -274,14 +301,15 @@ lp_build_swizzle_scalar_aos(struct lp_build_context *bld,
          LLVMValueRef tmp = NULL;
          int shift = shifts[channel][i];
 
-#ifdef PIPE_ARCH_LITTLE_ENDIAN
+         /* See endianness diagram above */
+#ifdef PIPE_ARCH_BIG_ENDIAN
          shift = -shift;
 #endif
 
          if(shift > 0)
-            tmp = LLVMBuildLShr(builder, a, lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
+            tmp = LLVMBuildShl(builder, a, lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
          if(shift < 0)
-            tmp = LLVMBuildShl(builder, a, lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
+            tmp = LLVMBuildLShr(builder, a, lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
 
          assert(tmp);
          if(tmp)
@@ -474,21 +502,39 @@ lp_build_swizzle_aos(struct lp_build_context *bld,
 
       /*
        * Mask and shift the channels, trying to group as many channels in the
-       * same shift as possible
+       * same shift as possible.  The shift amount is positive for shifts left
+       * and negative for shifts right.
        */
       for (shift = -3; shift <= 3; ++shift) {
          uint64_t mask = 0;
 
          assert(type4.width <= sizeof(mask)*8);
 
+         /*
+          * Vector element numbers follow the XYZW order, so 0 is always X, etc.
+          * After widening 4 times we have:
+          *
+          *                                3210
+          * Little-endian register layout: WZYX
+          *
+          *                                0123
+          * Big-endian register layout:    XYZW
+          *
+          * For little-endian, higher-numbered channels are obtained by a shift right
+          * (negative shift amount) and lower-numbered channels by a shift left
+          * (positive shift amount).  The opposite is true for big-endian.
+          */
          for (chan = 0; chan < 4; ++chan) {
-            /* FIXME: big endian */
-            if (swizzles[chan] < 4 &&
-                chan - swizzles[chan] == shift) {
+            if (swizzles[chan] < 4) {
+               /* We need to move channel swizzles[chan] into channel chan */
 #ifdef PIPE_ARCH_LITTLE_ENDIAN
-               mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width);
+               if (swizzles[chan] - chan == -shift) {
+                  mask |= ((1ULL << type.width) - 1) << (swizzles[chan] * type.width);
+               }
 #else
-               mask |= ((1ULL << type.width) - 1) << (type4.width - type.width) >> (swizzles[chan] * type.width);
+               if (swizzles[chan] - chan == shift) {
+                  mask |= ((1ULL << type.width) - 1) << (type4.width - type.width) >> (swizzles[chan] * type.width);
+               }
 #endif
             }
          }
@@ -502,21 +548,11 @@ lp_build_swizzle_aos(struct lp_build_context *bld,
             masked = LLVMBuildAnd(builder, a,
                                   lp_build_const_int_vec(bld->gallivm, type4, mask), "");
             if (shift > 0) {
-#ifdef PIPE_ARCH_LITTLE_ENDIAN
                shifted = LLVMBuildShl(builder, masked,
                                       lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
-#else
-               shifted = LLVMBuildLShr(builder, masked,
-                                       lp_build_const_int_vec(bld->gallivm, type4, shift*type.width), "");
-#endif
             } else if (shift < 0) {
-#ifdef PIPE_ARCH_LITTLE_ENDIAN
                shifted = LLVMBuildLShr(builder, masked,
                                        lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
-#else
-               shifted = LLVMBuildShl(builder, masked,
-                                      lp_build_const_int_vec(bld->gallivm, type4, -shift*type.width), "");
-#endif
             } else {
                shifted = masked;
             }
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
index 4cace6a..9774a2b 100644
--- a/src/gallium/auxiliary/util/u_format.h
+++ b/src/gallium/auxiliary/util/u_format.h
@@ -133,6 +133,7 @@ struct util_format_channel_description
    unsigned normalized:1;
    unsigned pure_integer:1;
    unsigned size:9;        /**< bits per channel */
+   unsigned shift:16;      /** number of bits from lsb */
 };
 
 
@@ -179,9 +180,31 @@ struct util_format_description
    unsigned is_mixed:1;
 
    /**
-    * Input channel description.
+    * Input channel description, in the order XYZW.
     *
     * Only valid for UTIL_FORMAT_LAYOUT_PLAIN formats.
+    *
+    * If each channel is accessed as an individual N-byte value, X is always
+    * at the lowest address in memory, Y is always next, and so on.  For all
+    * currently-defined formats, the N-byte value has native endianness.
+    *
+    * If instead a group of channels is accessed as a single N-byte value,
+    * the order of the channels within that value depends on endianness.
+    * For big-endian targets, X is the most significant subvalue,
+    * otherwise it is the least significant one.
+    *
+    * For example, if X is 8 bits and Y is 24 bits, the memory order is:
+    *
+    *                 0  1  2  3
+    *  little-endian: X  Yl Ym Yu    (l = lower, m = middle, u = upper)
+    *  big-endian:    X  Yu Ym Yl
+    *
+    * If X is 5 bits, Y is 5 bits, Z is 5 bits and W is 1 bit, the layout is:
+    *
+    *                        0        1
+    *                 msb  lsb msb  lsb
+    *  little-endian: YYYXXXXX WZZZZZYY
+    *  big-endian:    XXXXXYYY YYZZZZZW
     */
    struct util_format_channel_description channel[4];
 
diff --git a/src/gallium/auxiliary/util/u_format_pack.py b/src/gallium/auxiliary/util/u_format_pack.py
index de59b38..d1f68c8 100644
--- a/src/gallium/auxiliary/util/u_format_pack.py
+++ b/src/gallium/auxiliary/util/u_format_pack.py
@@ -415,10 +415,10 @@ def generate_unpack_kernel(format, dst_channel, dst_native_type):
                 print '         int%u_t %s;' % (depth, src_channel.name)
 
         # Compute the intermediate unshifted values 
-        shift = 0
         for i in range(format.nr_channels()):
             src_channel = format.channels[i]
             value = 'value'
+            shift = src_channel.shift
             if src_channel.type == UNSIGNED:
                 if shift:
                     value = '%s >> %u' % (value, shift)
@@ -441,8 +441,6 @@ def generate_unpack_kernel(format, dst_channel, dst_native_type):
             if value is not None:
                 print '         %s = %s;' % (src_channel.name, value)
                 
-            shift += src_channel.size
-
         # Convert, swizzle, and store final values
         for i in range(4):
             swizzle = format.swizzles[i]
@@ -510,9 +508,9 @@ def generate_pack_kernel(format, src_channel, src_native_type):
         depth = format.block_size()
         print '         uint%u_t value = 0;' % depth 
 
-        shift = 0
         for i in range(4):
             dst_channel = format.channels[i]
+            shift = dst_channel.shift
             if inv_swizzle[i] is not None:
                 value ='src[%u]' % inv_swizzle[i]
                 dst_colorspace = format.colorspace
@@ -536,8 +534,6 @@ def generate_pack_kernel(format, src_channel, src_native_type):
                 if value is not None:
                     print '         value |= %s;' % (value)
                 
-            shift += dst_channel.size
-
         print '         *(uint%u_t *)dst = value;' % depth 
 
     else:
diff --git a/src/gallium/auxiliary/util/u_format_parse.py b/src/gallium/auxiliary/util/u_format_parse.py
index 07052b9..e202099 100755
--- a/src/gallium/auxiliary/util/u_format_parse.py
+++ b/src/gallium/auxiliary/util/u_format_parse.py
@@ -30,6 +30,8 @@
 '''
 
 
+import sys
+
 VOID, UNSIGNED, SIGNED, FIXED, FLOAT = range(5)
 
 SWIZZLE_X, SWIZZLE_Y, SWIZZLE_Z, SWIZZLE_W, SWIZZLE_0, SWIZZLE_1, SWIZZLE_NONE, = range(7)
@@ -42,6 +44,9 @@ YUV = 'yuv'
 ZS = 'zs'
 
 
+# Not cross-compiler friendly
+is_big_endian = sys.byteorder == 'big'
+
 def is_pot(x):
    return (x & (x - 1)) == 0
 
@@ -307,6 +312,11 @@ def parse(filename):
             channel = Channel(type, norm, pure, size, names[i])
             channels.append(channel)
 
+        shift = 0
+        for channel in channels[3::-1] if is_big_endian else channels:
+            channel.shift = shift
+            shift += channel.size
+
         format = Format(name, layout, block_width, block_height, channels, swizzles, colorspace)
         formats.append(format)
     return formats
diff --git a/src/gallium/auxiliary/util/u_format_table.py b/src/gallium/auxiliary/util/u_format_table.py
index 8edb505..9d44cf3 100755
--- a/src/gallium/auxiliary/util/u_format_table.py
+++ b/src/gallium/auxiliary/util/u_format_table.py
@@ -114,9 +114,9 @@ def write_format_table(formats):
             else:
                 sep = ""
             if channel.size:
-                print "      {%s, %s, %s, %u}%s\t/* %s = %s */" % (type_map[channel.type], bool_map(channel.norm), bool_map(channel.pure), channel.size, sep, "xyzw"[i], channel.name)
+                print "      {%s, %s, %s, %u, %u}%s\t/* %s = %s */" % (type_map[channel.type], bool_map(channel.norm), bool_map(channel.pure), channel.size, channel.shift, sep, "xyzw"[i], channel.name)
             else:
-                print "      {0, 0, 0, 0}%s" % (sep,)
+                print "      {0, 0, 0, 0, 0}%s" % (sep,)
         print "   },"
         print "   {"
         for i in range(4):
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
index edb59cc..8016995 100644
--- a/src/gallium/drivers/llvmpipe/lp_bld_depth.c
+++ b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
@@ -349,8 +349,6 @@ get_z_shift_and_mask(const struct util_format_description *format_desc,
 {
    unsigned total_bits;
    unsigned z_swizzle;
-   unsigned chan;
-   unsigned padding_left, padding_right;
 
    assert(format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS);
    assert(format_desc->block.width == 1);
@@ -365,25 +363,14 @@ get_z_shift_and_mask(const struct util_format_description *format_desc,
       return FALSE;
 
    *width = format_desc->channel[z_swizzle].size;
+   *shift = format_desc->channel[z_swizzle].shift;
 
-   padding_right = 0;
-   for (chan = 0; chan < z_swizzle; ++chan)
-      padding_right += format_desc->channel[chan].size;
-
-   padding_left =
-      total_bits - (padding_right + *width);
-
-   if (padding_left || padding_right) {
-      unsigned long long mask_left = (1ULL << (total_bits - padding_left)) - 1;
-      unsigned long long mask_right = (1ULL << (padding_right)) - 1;
-      *mask = mask_left ^ mask_right;
-   }
-   else {
+   if (*width == total_bits) {
       *mask = 0xffffffff;
+   } else {
+      *mask = ((1 << *width) - 1) << *shift;
    }
 
-   *shift = padding_right;
-
    return TRUE;
 }
 
@@ -398,7 +385,7 @@ get_s_shift_and_mask(const struct util_format_description *format_desc,
                      unsigned *shift, unsigned *mask)
 {
    unsigned s_swizzle;
-   unsigned chan, sz;
+   unsigned sz;
 
    s_swizzle = format_desc->swizzle[1];
 
@@ -407,16 +394,14 @@ get_s_shift_and_mask(const struct util_format_description *format_desc,
 
    /* just special case 64bit d/s format */
    if (format_desc->block.bits > 32) {
+      /* XXX big-endian? */
       assert(format_desc->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT);
       *shift = 0;
       *mask = 0xff;
       return TRUE;
    }
 
-   *shift = 0;
-   for (chan = 0; chan < s_swizzle; chan++)
-      *shift += format_desc->channel[chan].size;
-
+   *shift = format_desc->channel[s_swizzle].shift;
    sz = format_desc->channel[s_swizzle].size;
    *mask = (1U << sz) - 1U;
 
-- 
1.8.2.1



More information about the mesa-dev mailing list