[Mesa-dev] Wrong colors in 3D apps on big-endian systems

Submitted by Christian Zigotzky on March 10, 2014, 9:11 a.m.

Details

Message ID 531D81BA.3090001@xenosoft.de
State New
Headers show

Not browsing as part of any series.

Commit Message

Christian Zigotzky March 10, 2014, 9:11 a.m.
Hi Michel,

On 10.03.2014 02:49, Michel Dänzer wrote:
>
> Congratulations, you just broke llvmpipe again on big endian systems. ;)
I'm sorry but Mesa classic works very well on Debian Sid and Lubuntu 
14.04 with these changes. ;) Why does Mesa classic work with the 
little-endian defines?
> Did you even look at the commits introducing those defines? Did you
> really think those defines, with explicit endianness checks, were
> introduced for no reason but to break drivers on big endian systems?
>
>
> I explained the problem in r600g and how it could be solved. Please
> explore that.
I'll try to explore that but I don't have any knowledge about the Mesa 
source code. The Fedora guys have solved the problem with the patch 
"mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?

Rgds,
Christian

Patch hide | download patch | download mbox

diff --git a/src/gallium/auxiliary/draw/draw_private.h b/src/gallium/auxiliary/draw/draw_private.h
index f30f9af..adde647 100644
--- a/src/gallium/auxiliary/draw/draw_private.h
+++ b/src/gallium/auxiliary/draw/draw_private.h
@@ -71,7 +71,7 @@  struct draw_pt_front_end;
  */
 struct draw_vertex_buffer {
    const void *map;
-   size_t size;
+   uint32_t size;
 };
 
 /**
diff --git a/src/gallium/auxiliary/draw/draw_pt.c b/src/gallium/auxiliary/draw/draw_pt.c
index 131bd13..720d7b1 100644
--- a/src/gallium/auxiliary/draw/draw_pt.c
+++ b/src/gallium/auxiliary/draw/draw_pt.c
@@ -326,6 +326,13 @@  draw_print_arrays(struct draw_context *draw, uint prim, int start, uint count)
                             (void *) u);
             }
             break;
+         case PIPE_FORMAT_A8R8G8B8_UNORM:
+            {
+               ubyte *u = (ubyte *) ptr;
+               debug_printf("ARGB %d %d %d %d  @ %p\n", u[0], u[1], u[2], u[3],
+                            (void *) u);
+            }
+            break;
          default:
             debug_printf("other format %s (fix me)\n",
                      util_format_name(draw->pt.vertex_element[j].src_format));
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_arit.c b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
index 3291ec4..08aec79 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_arit.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_arit.c
@@ -386,6 +386,10 @@  lp_build_add(struct lp_build_context *bld,
          return lp_build_intrinsic_binary(builder, intrinsic, lp_build_vec_type(bld->gallivm, bld->type), a, b);
    }
 
+   /* TODO: handle signed case */
+   if(type.norm && !type.floating && !type.fixed && !type.sign)
+      a = lp_build_min_simple(bld, a, lp_build_comp(bld, b));
+
    if(LLVMIsConstant(a) && LLVMIsConstant(b))
       if (type.floating)
          res = LLVMConstFAdd(a, b);
@@ -663,6 +667,10 @@  lp_build_sub(struct lp_build_context *bld,
          return lp_build_intrinsic_binary(builder, intrinsic, lp_build_vec_type(bld->gallivm, bld->type), a, b);
    }
 
+   /* TODO: handle signed case */
+   if(type.norm && !type.floating && !type.fixed && !type.sign)
+      a = lp_build_max_simple(bld, a, b);
+
    if(LLVMIsConstant(a) && LLVMIsConstant(b))
       if (type.floating)
          res = LLVMConstFSub(a, b);
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
index f11361a..cbea966 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_conv.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
@@ -80,82 +80,6 @@ 
 
 
 /**
- * Byte swap on element. It will construct a call to intrinsic llvm.bswap
- * based on the type.
- *
- * @param res           element to byte swap.
- * @param type          int16_t, int32_t, int64_t, float or double
- * @param 
- */
-LLVMValueRef
-lp_build_bswap(struct gallivm_state *gallivm,
-               LLVMValueRef res,
-               struct lp_type type)
-{
-   LLVMTypeRef int_type = LLVMIntTypeInContext(gallivm->context,
-                                               type.width);
-   const char *intrinsic = NULL;
-   if (type.width == 8)
-      return res;
-   if (type.width == 16)
-      intrinsic = "llvm.bswap.i16";
-   else if (type.width == 32)
-     intrinsic = "llvm.bswap.i32";
-   else if (type.width == 64)
-      intrinsic = "llvm.bswap.i64";
-
-   assert (intrinsic != NULL);
-
-   /* In case of a floating-point type cast to a int of same size and then
-    * cast back to fp type.
-    */
-   if (type.floating)
-      res = LLVMBuildBitCast(gallivm->builder, res, int_type, "");
-   res = lp_build_intrinsic_unary(gallivm->builder, intrinsic, int_type, res);
-   if (type.floating)
-      res = LLVMBuildBitCast(gallivm->builder, res,
-                             lp_build_elem_type(gallivm, type), "");
-   return res;
-}
-
-
-/**
- * Byte swap every element in the vector.
- *
- * @param packed        <vector> to convert
- * @param src_type      <vector> type of int16_t, int32_t, int64_t, float or
- *                      double
- * @param dst_type      <vector> type to return
- */
-LLVMValueRef
-lp_build_bswap_vec(struct gallivm_state *gallivm,
-                   LLVMValueRef packed,
-                   struct lp_type src_type_vec,
-                   struct lp_type dst_type_vec)
-{
-   LLVMBuilderRef builder = gallivm->builder;
-   LLVMTypeRef dst_type = lp_build_elem_type(gallivm, dst_type_vec);
-   LLVMValueRef res;
-
-   if (src_type_vec.length == 1) {
-      res = lp_build_bswap(gallivm, packed, src_type_vec);
-      res = LLVMBuildBitCast(gallivm->builder, res, dst_type, "");
-   } else {
-      unsigned i;
-      res = LLVMGetUndef(lp_build_vec_type(gallivm, dst_type_vec));
-      for (i = 0; i < src_type_vec.length; ++i) {
-         LLVMValueRef index = lp_build_const_int32(gallivm, i);
-         LLVMValueRef elem = LLVMBuildExtractElement(builder, packed, index, "");
-         elem = lp_build_bswap(gallivm, elem, src_type_vec);
-         elem = LLVMBuildBitCast(gallivm->builder, elem, dst_type, "");
-         res = LLVMBuildInsertElement(gallivm->builder, res, elem, index, "");
-      }
-   }
-   return res;
-}
-
-
-/**
  * Converts int16 half-float to float32
  * Note this can be performed in 1 instruction if vcvtph2ps exists (f16c/cvt16)
  * [llvm.x86.vcvtph2ps / _mm_cvtph_ps]
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.h b/src/gallium/auxiliary/gallivm/lp_bld_conv.h
index d7dfed8..42a1113 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_conv.h
+++ b/src/gallium/auxiliary/gallivm/lp_bld_conv.h
@@ -43,17 +43,6 @@ 
 struct lp_type;
 
 LLVMValueRef
-lp_build_bswap(struct gallivm_state *gallivm,
-               LLVMValueRef res,
-               struct lp_type type);
-
-LLVMValueRef
-lp_build_bswap_vec(struct gallivm_state *gallivm,
-                   LLVMValueRef packed,
-                   struct lp_type src_type,
-                   struct lp_type dst_type);
-
-LLVMValueRef
 lp_build_half_to_float(struct gallivm_state *gallivm,
                        LLVMValueRef src);
 
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos.c
index 6a1bf67..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 */
@@ -172,10 +171,6 @@  lp_build_unpack_arith_rgba_aos(struct gallivm_state *gallivm,
     * matches floating point size */
    assert (LLVMTypeOf(packed) == LLVMInt32TypeInContext(gallivm->context));
 
-#ifdef PIPE_ARCH_BIG_ENDIAN
-   packed = lp_build_bswap(gallivm, packed, lp_type_uint(32));
-#endif
-
    /* Broadcast the packed value to all four channels
     * before: packed = BGRA
     * after: packed = {BGRA, BGRA, BGRA, BGRA}
@@ -194,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));
@@ -224,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), "");
@@ -276,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);
@@ -302,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));
@@ -325,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)
@@ -410,16 +400,11 @@  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);
 
       packed = LLVMBuildBitCast(gallivm->builder, packed, dst_vec_type, "");
-#ifdef PIPE_ARCH_BIG_ENDIAN
-      if (type.floating)
-         packed = lp_build_bswap_vec(gallivm, packed, type,
-                                    lp_type_float_vec(type.width, vec_len));
-#endif
       return lp_build_format_swizzle_aos(format_desc, &bld, packed);
    }
 
@@ -453,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_aos_array.c b/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c
index 3402a0b..ee3ca86 100644
--- a/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c
+++ b/src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c
@@ -40,58 +40,6 @@ 
 #include "pipe/p_state.h"
 
 
-#ifdef PIPE_ARCH_BIG_ENDIAN
-static LLVMValueRef
-lp_build_read_int_bswap(struct gallivm_state *gallivm,
-                        LLVMValueRef base_ptr,
-                        unsigned src_width,
-                        LLVMTypeRef src_type,
-                        unsigned i,
-                        LLVMTypeRef dst_type)
-{
-   LLVMBuilderRef builder = gallivm->builder;
-   LLVMValueRef index = lp_build_const_int32(gallivm, i);
-   LLVMValueRef ptr = LLVMBuildGEP(builder, base_ptr, &index, 1, "");
-   LLVMValueRef res = LLVMBuildLoad(builder, ptr, "");
-   res = lp_build_bswap(gallivm, res, lp_type_uint(src_width));
-   return LLVMBuildBitCast(builder, res, dst_type, "");
-}
-
-static LLVMValueRef
-lp_build_fetch_read_big_endian(struct gallivm_state *gallivm,
-                               struct lp_type src_type,
-                               LLVMValueRef base_ptr)
-{
-   LLVMBuilderRef builder = gallivm->builder;
-   unsigned src_width = src_type.width;
-   unsigned length = src_type.length;
-   LLVMTypeRef src_elem_type = LLVMIntTypeInContext(gallivm->context, src_width);
-   LLVMTypeRef dst_elem_type = lp_build_elem_type (gallivm, src_type);
-   LLVMTypeRef src_ptr_type = LLVMPointerType(src_elem_type, 0);
-   LLVMValueRef res;
-
-   base_ptr = LLVMBuildPointerCast(builder, base_ptr, src_ptr_type, "");
-   if (length == 1) {
-      /* Scalar */
-      res = lp_build_read_int_bswap(gallivm, base_ptr, src_width, src_elem_type,
-                                    0, dst_elem_type);
-   } else {
-      /* Vector */
-      LLVMTypeRef dst_vec_type = LLVMVectorType(dst_elem_type, length);
-      unsigned i;
-
-      res = LLVMGetUndef(dst_vec_type);
-      for (i = 0; i < length; ++i) {
-         LLVMValueRef index = lp_build_const_int32(gallivm, i);
-         LLVMValueRef elem = lp_build_read_int_bswap(gallivm, base_ptr, src_width,
-                                                     src_elem_type, i, dst_elem_type);
-         res = LLVMBuildInsertElement(builder, res, elem, index, "");
-      }
-   }
-
-   return res;
-}
-#endif
 
 /**
  * @brief lp_build_fetch_rgba_aos_array
@@ -124,13 +72,9 @@  lp_build_fetch_rgba_aos_array(struct gallivm_state *gallivm,
 
    /* Read whole vector from memory, unaligned */
    ptr = LLVMBuildGEP(builder, base_ptr, &offset, 1, "");
-#ifdef PIPE_ARCH_BIG_ENDIAN
-   res = lp_build_fetch_read_big_endian(gallivm, src_type, ptr);
-#else
    ptr = LLVMBuildPointerCast(builder, ptr, LLVMPointerType(src_vec_type, 0), "");
    res = LLVMBuildLoad(builder, ptr, "");
    lp_set_load_alignment(res, src_type.width / 8);
-#endif
 
    /* Truncate doubles to float */
    if (src_type.floating && src_type.width == 64) {
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c b/src/gallium/auxiliary/gallivm/lp_bld_format_soa.c
index edc2442..4c6bd81 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);
@@ -291,7 +288,11 @@  lp_build_rgba8_to_fi32_soa(struct gallivm_state *gallivm,
 
    /* Decode the input vector components */
    for (chan = 0; chan < 4; ++chan) {
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
       unsigned start = chan*8;
+#else
+      unsigned start = (3-chan)*8;
+#endif
       unsigned stop = start + 8;
       LLVMValueRef input;
 
@@ -360,13 +361,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 +393,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 +421,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_cpu_detect.c b/src/gallium/auxiliary/util/u_cpu_detect.c
index 7e6df9d..763b5cc 100644
--- a/src/gallium/auxiliary/util/u_cpu_detect.c
+++ b/src/gallium/auxiliary/util/u_cpu_detect.c
@@ -250,6 +250,11 @@  util_cpu_detect(void)
    util_cpu_caps.nr_cpus = 1;
 #endif
 
+   /* Make the fallback cacheline size nonzero so that it can be
+    * safely passed to align().
+    */
+   util_cpu_caps.cacheline = sizeof(void *);
+
 #if defined(PIPE_ARCH_X86) || defined(PIPE_ARCH_X86_64)
    if (has_cpuid()) {
       uint32_t regs[4];
diff --git a/src/gallium/auxiliary/util/u_format.h b/src/gallium/auxiliary/util/u_format.h
index e4b9c36..3a04d89 100644
--- a/src/gallium/auxiliary/util/u_format.h
+++ b/src/gallium/auxiliary/util/u_format.h
@@ -132,6 +132,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 */
 };
 
 
@@ -178,9 +179,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 565d059..d1f68c8 100644
--- a/src/gallium/auxiliary/util/u_format_pack.py
+++ b/src/gallium/auxiliary/util/u_format_pack.py
@@ -99,15 +99,6 @@  def generate_format_type(format):
     print
 
 
-def bswap_format(format):
-    '''Generate a structure that describes the format.'''
-
-    if format.is_bitmask() and not format.is_array() and format.block_size() > 8:
-        print '#ifdef PIPE_ARCH_BIG_ENDIAN'
-        print '   pixel.value = util_bswap%u(pixel.value);' % format.block_size()
-        print '#endif'
-
-
 def is_format_supported(format):
     '''Determines whether we actually have the plumbing necessary to generate the 
     to read/write to/from this format.'''
@@ -423,16 +414,11 @@  def generate_unpack_kernel(format, dst_channel, dst_native_type):
             elif src_channel.type == SIGNED:
                 print '         int%u_t %s;' % (depth, src_channel.name)
 
-        if depth > 8:
-            print '#ifdef PIPE_ARCH_BIG_ENDIAN'
-            print '         value = util_bswap%u(value);' % depth
-            print '#endif'
-
         # 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)
@@ -455,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]
@@ -484,7 +468,6 @@  def generate_unpack_kernel(format, dst_channel, dst_native_type):
     else:
         print '         union util_format_%s pixel;' % format.short_name()
         print '         memcpy(&pixel, src, sizeof pixel);'
-        bswap_format(format)
     
         for i in range(4):
             swizzle = format.swizzles[i]
@@ -525,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
@@ -551,13 +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
-
-        if depth > 8:
-            print '#ifdef PIPE_ARCH_BIG_ENDIAN'
-            print '         value = util_bswap%u(value);' % depth
-            print '#endif'
-        
         print '         *(uint%u_t *)dst = value;' % depth 
 
     else:
@@ -579,7 +555,6 @@  def generate_pack_kernel(format, src_channel, src_native_type):
                                     dst_colorspace = dst_colorspace)
             print '         pixel.chan.%s = %s;' % (dst_channel.name, value)
     
-        bswap_format(format)
         print '         memcpy(dst, &pixel, sizeof pixel);'
     
 
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/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h
index 1f6a56a..9c25451 100644
--- a/src/gallium/auxiliary/util/u_pack_color.h
+++ b/src/gallium/auxiliary/util/u_pack_color.h
@@ -65,32 +65,32 @@  util_pack_color_ub(ubyte r, ubyte g, ubyte b, ubyte a,
                    enum pipe_format format, union util_color *uc)
 {
    switch (format) {
-   case PIPE_FORMAT_A8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBA8888_UNORM:
       {
          uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
       }
       return;
-   case PIPE_FORMAT_X8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBX8888_UNORM:
       {
          uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
       }
       return;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_ARGB8888_UNORM:
       {
          uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
       }
       return;
-   case PIPE_FORMAT_B8G8R8X8_UNORM:
+   case PIPE_FORMAT_XRGB8888_UNORM:
       {
          uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
       }
       return;
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRA8888_UNORM:
       {
          uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
       }
       return;
-   case PIPE_FORMAT_X8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRX8888_UNORM:
       {
          uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
       }
@@ -166,7 +166,7 @@  util_unpack_color_ub(enum pipe_format format, union util_color *uc,
                      ubyte *r, ubyte *g, ubyte *b, ubyte *a)
 {
    switch (format) {
-   case PIPE_FORMAT_A8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBA8888_UNORM:
       {
          uint p = uc->ui;
          *r = (ubyte) ((p >> 24) & 0xff);
@@ -175,7 +175,7 @@  util_unpack_color_ub(enum pipe_format format, union util_color *uc,
          *a = (ubyte) ((p >>  0) & 0xff);
       }
       return;
-   case PIPE_FORMAT_X8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBX8888_UNORM:
       {
          uint p = uc->ui;
          *r = (ubyte) ((p >> 24) & 0xff);
@@ -184,7 +184,7 @@  util_unpack_color_ub(enum pipe_format format, union util_color *uc,
          *a = (ubyte) 0xff;
       }
       return;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_ARGB8888_UNORM:
       {
          uint p = uc->ui;
          *r = (ubyte) ((p >> 16) & 0xff);
@@ -193,7 +193,7 @@  util_unpack_color_ub(enum pipe_format format, union util_color *uc,
          *a = (ubyte) ((p >> 24) & 0xff);
       }
       return;
-   case PIPE_FORMAT_B8G8R8X8_UNORM:
+   case PIPE_FORMAT_XRGB8888_UNORM:
       {
          uint p = uc->ui;
          *r = (ubyte) ((p >> 16) & 0xff);
@@ -202,7 +202,7 @@  util_unpack_color_ub(enum pipe_format format, union util_color *uc,
          *a = (ubyte) 0xff;
       }
       return;
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRA8888_UNORM:
       {
          uint p = uc->ui;
          *r = (ubyte) ((p >>  8) & 0xff);
@@ -211,7 +211,7 @@  util_unpack_color_ub(enum pipe_format format, union util_color *uc,
          *a = (ubyte) ((p >>  0) & 0xff);
       }
       return;
-   case PIPE_FORMAT_X8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRX8888_UNORM:
       {
          uint p = uc->ui;
          *r = (ubyte) ((p >>  8) & 0xff);
@@ -350,32 +350,32 @@  util_pack_color(const float rgba[4], enum pipe_format format, union util_color *
    }
 
    switch (format) {
-   case PIPE_FORMAT_A8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBA8888_UNORM:
       {
          uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
       }
       return;
-   case PIPE_FORMAT_X8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBX8888_UNORM:
       {
          uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
       }
       return;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_ARGB8888_UNORM:
       {
          uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
       }
       return;
-   case PIPE_FORMAT_B8G8R8X8_UNORM:
+   case PIPE_FORMAT_XRGB8888_UNORM:
       {
          uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
       }
       return;
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRA8888_UNORM:
       {
          uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
       }
       return;
-   case PIPE_FORMAT_X8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRX8888_UNORM:
       {
          uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
       }
diff --git a/src/gallium/drivers/llvmpipe/lp_bld_depth.c b/src/gallium/drivers/llvmpipe/lp_bld_depth.c
index a8bd15f..f322131 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;
 
diff --git a/src/gallium/drivers/llvmpipe/lp_state_fs.c b/src/gallium/drivers/llvmpipe/lp_state_fs.c
index fc2ba5e..38e9fc7 100644
--- a/src/gallium/drivers/llvmpipe/lp_state_fs.c
+++ b/src/gallium/drivers/llvmpipe/lp_state_fs.c
@@ -1015,12 +1015,17 @@  convert_to_blend_type(struct gallivm_state *gallivm,
    for (i = 0; i < num_srcs; ++i) {
       LLVMValueRef chans[4];
       LLVMValueRef res = NULL;
-      unsigned sa = 0;
 
       dst[i] = LLVMBuildZExt(builder, src[i], lp_build_vec_type(gallivm, src_type), "");
 
       for (j = 0; j < src_fmt->nr_channels; ++j) {
          unsigned mask = 0;
+         unsigned sa = src_fmt->channel[j].shift;
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
+         unsigned from_lsb = j;
+#else
+         unsigned from_lsb = src_fmt->nr_channels - j - 1;
+#endif
 
          for (k = 0; k < src_fmt->channel[j].size; ++k) {
             mask |= 1 << k;
@@ -1046,11 +1051,9 @@  convert_to_blend_type(struct gallivm_state *gallivm,
          /* Insert bits into correct position */
          chans[j] = LLVMBuildShl(builder,
                                  chans[j],
-                                 lp_build_const_int_vec(gallivm, src_type, j * blend_type.width),
+                                 lp_build_const_int_vec(gallivm, src_type, from_lsb * blend_type.width),
                                  "");
 
-         sa += src_fmt->channel[j].size;
-
          if (j == 0) {
             res = chans[j];
          } else {
@@ -1166,12 +1169,17 @@  convert_from_blend_type(struct gallivm_state *gallivm,
    for (i = 0; i < num_srcs; ++i) {
       LLVMValueRef chans[4];
       LLVMValueRef res = NULL;
-      unsigned sa = 0;
 
       dst[i] = LLVMBuildBitCast(builder, src[i], lp_build_vec_type(gallivm, src_type), "");
 
       for (j = 0; j < src_fmt->nr_channels; ++j) {
          unsigned mask = 0;
+         unsigned sa = src_fmt->channel[j].shift;
+#ifdef PIPE_ARCH_LITTLE_ENDIAN
+         unsigned from_lsb = j;
+#else
+         unsigned from_lsb = src_fmt->nr_channels - j - 1;
+#endif
 
          assert(blend_type.width > src_fmt->channel[j].size);
 
@@ -1182,7 +1190,7 @@  convert_from_blend_type(struct gallivm_state *gallivm,
          /* Extract bits */
          chans[j] = LLVMBuildLShr(builder,
                                   dst[i],
-                                  lp_build_const_int_vec(gallivm, src_type, j * blend_type.width),
+                                  lp_build_const_int_vec(gallivm, src_type, from_lsb * blend_type.width),
                                   "");
 
          chans[j] = LLVMBuildAnd(builder,
diff --git a/src/gallium/include/pipe/p_format.h b/src/gallium/include/pipe/p_format.h
index 098b25b..1289983 100644
--- a/src/gallium/include/pipe/p_format.h
+++ b/src/gallium/include/pipe/p_format.h
@@ -33,6 +33,7 @@ 
 extern "C" {
 #endif
 
+#include "p_config.h"
 
 enum pipe_type {
    PIPE_TYPE_UNORM = 0,
@@ -53,10 +54,10 @@  enum pipe_type {
 
 enum pipe_format {
    PIPE_FORMAT_NONE                    = 0,
-   PIPE_FORMAT_B8G8R8A8_UNORM          = 1,
-   PIPE_FORMAT_B8G8R8X8_UNORM          = 2,
-   PIPE_FORMAT_A8R8G8B8_UNORM          = 3,
-   PIPE_FORMAT_X8R8G8B8_UNORM          = 4,
+   PIPE_FORMAT_ARGB8888_UNORM          = 1,
+   PIPE_FORMAT_XRGB8888_UNORM          = 2,
+   PIPE_FORMAT_BGRA8888_UNORM          = 3,
+   PIPE_FORMAT_BGRX8888_UNORM          = 4,
    PIPE_FORMAT_B5G5R5A1_UNORM          = 5,
    PIPE_FORMAT_B4G4R4A4_UNORM          = 6,
    PIPE_FORMAT_B5G6R5_UNORM            = 7,
@@ -119,8 +120,8 @@  enum pipe_format {
    PIPE_FORMAT_R8_UNORM                = 64,
    PIPE_FORMAT_R8G8_UNORM              = 65,
    PIPE_FORMAT_R8G8B8_UNORM            = 66,
-   PIPE_FORMAT_R8G8B8A8_UNORM          = 67,
-   PIPE_FORMAT_X8B8G8R8_UNORM          = 68,
+   PIPE_FORMAT_ABGR8888_UNORM          = 67,
+   PIPE_FORMAT_RGBX8888_UNORM          = 68,
    PIPE_FORMAT_R8_USCALED              = 69,
    PIPE_FORMAT_R8G8_USCALED            = 70,
    PIPE_FORMAT_R8G8B8_USCALED          = 71,
@@ -180,7 +181,7 @@  enum pipe_format {
    PIPE_FORMAT_R5SG5SB6U_NORM          = 120,
 
    /* TODO: re-order these */
-   PIPE_FORMAT_A8B8G8R8_UNORM          = 121,
+   PIPE_FORMAT_RGBA8888_UNORM          = 121,
    PIPE_FORMAT_B5G5R5X1_UNORM          = 122,
    PIPE_FORMAT_R10G10B10A2_USCALED     = 123,
    PIPE_FORMAT_R11G11B10_FLOAT         = 124,
@@ -193,7 +194,7 @@  enum pipe_format {
    PIPE_FORMAT_B10G10R10A2_UNORM       = 131,
    PIPE_FORMAT_R10SG10SB10SA2U_NORM    = 132,
    PIPE_FORMAT_R8G8Bx_SNORM            = 133,
-   PIPE_FORMAT_R8G8B8X8_UNORM          = 134,
+   PIPE_FORMAT_XBGR8888_UNORM          = 134,
    PIPE_FORMAT_B4G4R4X4_UNORM          = 135,
 
    /* some stencil samplers formats */
@@ -343,6 +344,27 @@  enum pipe_format {
    PIPE_FORMAT_COUNT
 };
 
+#if defined(PIPE_ARCH_LITTLE_ENDIAN)
+#define PIPE_FORMAT_R8G8B8A8_UNORM PIPE_FORMAT_ABGR8888_UNORM
+#define PIPE_FORMAT_R8G8B8X8_UNORM PIPE_FORMAT_XBGR8888_UNORM
+#define PIPE_FORMAT_B8G8R8X8_UNORM PIPE_FORMAT_XRGB8888_UNORM
+#define PIPE_FORMAT_B8G8R8A8_UNORM PIPE_FORMAT_ARGB8888_UNORM
+#define PIPE_FORMAT_B8G8R8X8_UNORM PIPE_FORMAT_XRGB8888_UNORM
+#define PIPE_FORMAT_A8R8G8B8_UNORM PIPE_FORMAT_BGRA8888_UNORM
+#define PIPE_FORMAT_X8R8G8B8_UNORM PIPE_FORMAT_BGRX8888_UNORM
+#define PIPE_FORMAT_A8B8G8R8_UNORM PIPE_FORMAT_RGBA8888_UNORM
+#define PIPE_FORMAT_X8B8G8R8_UNORM PIPE_FORMAT_RGBX8888_UNORM
+#elif defined(PIPE_ARCH_BIG_ENDIAN)
+#define PIPE_FORMAT_R8G8B8A8_UNORM PIPE_FORMAT_RGBA8888_UNORM
+#define PIPE_FORMAT_R8G8B8X8_UNORM PIPE_FORMAT_RGBX8888_UNORM
+#define PIPE_FORMAT_B8G8R8A8_UNORM PIPE_FORMAT_BGRA8888_UNORM
+#define PIPE_FORMAT_B8G8R8X8_UNORM PIPE_FORMAT_BGRX8888_UNORM
+#define PIPE_FORMAT_A8R8G8B8_UNORM PIPE_FORMAT_ARGB8888_UNORM
+#define PIPE_FORMAT_X8R8G8B8_UNORM PIPE_FORMAT_XRGB8888_UNORM
+#define PIPE_FORMAT_A8B8G8R8_UNORM PIPE_FORMAT_ABGR8888_UNORM
+#define PIPE_FORMAT_X8B8G8R8_UNORM PIPE_FORMAT_XBGR8888_UNORM
+#endif
+
 enum pipe_video_chroma_format
 {
    PIPE_VIDEO_CHROMA_FORMAT_420,
diff --git a/src/gallium/state_trackers/dri/common/dri_screen.c b/src/gallium/state_trackers/dri/common/dri_screen.c
index e09fe1d..43cca30 100644
--- a/src/gallium/state_trackers/dri/common/dri_screen.c
+++ b/src/gallium/state_trackers/dri/common/dri_screen.c
@@ -87,8 +87,8 @@  dri_fill_in_modes(struct dri_screen *screen)
       MESA_FORMAT_RGB565,
    };
    static const enum pipe_format pipe_formats[3] = {
-      PIPE_FORMAT_B8G8R8A8_UNORM,
-      PIPE_FORMAT_B8G8R8X8_UNORM,
+      PIPE_FORMAT_ARGB8888_UNORM,
+      PIPE_FORMAT_XRGB8888_UNORM,
       PIPE_FORMAT_B5G6R5_UNORM,
    };
    gl_format format;
@@ -250,11 +250,11 @@  dri_fill_st_visual(struct st_visual *stvis, struct dri_screen *screen,
 
    if (mode->redBits == 8) {
       if (mode->alphaBits == 8)
-         stvis->color_format = PIPE_FORMAT_B8G8R8A8_UNORM;
+         stvis->color_format = PIPE_FORMAT_ARGB8888_UNORM;
       else
-         stvis->color_format = PIPE_FORMAT_B8G8R8X8_UNORM;
+         stvis->color_format = PIPE_FORMAT_XRGB8888_UNORM;
    } else {
-      stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM;
+      stvis->color_format = PIPE_FORMAT_B5G6R5_UNORM; /* XXX big-endian? */
    }
 
    if (mode->sampleBuffers) {
diff --git a/src/gallium/state_trackers/gbm/gbm_drm.c b/src/gallium/state_trackers/gbm/gbm_drm.c
index 8490480..4f76b0f 100644
--- a/src/gallium/state_trackers/gbm/gbm_drm.c
+++ b/src/gallium/state_trackers/gbm/gbm_drm.c
@@ -45,9 +45,9 @@  gbm_format_to_gallium(enum gbm_bo_format format)
 {
    switch (format) {
    case GBM_BO_FORMAT_XRGB8888:
-      return PIPE_FORMAT_B8G8R8X8_UNORM;
+      return PIPE_FORMAT_XRGB8888_UNORM;
    case GBM_BO_FORMAT_ARGB8888:
-      return PIPE_FORMAT_B8G8R8A8_UNORM;
+      return PIPE_FORMAT_ARGB8888_UNORM;
    default:
       return PIPE_FORMAT_NONE;
    }
@@ -145,10 +145,10 @@  gbm_gallium_drm_bo_import(struct gbm_device *gbm,
    bo->base.base.height = resource->height0;
 
    switch (resource->format) {
-   case PIPE_FORMAT_B8G8R8X8_UNORM:
+   case PIPE_FORMAT_XRGB8888_UNORM:
       bo->base.base.format = GBM_BO_FORMAT_XRGB8888;
       break;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_ARGB8888_UNORM:
       bo->base.base.format = GBM_BO_FORMAT_ARGB8888;
       break;
    default:
diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c
index b758c8e..5f187e5 100644
--- a/src/gallium/state_trackers/glx/xlib/xm_api.c
+++ b/src/gallium/state_trackers/glx/xlib/xm_api.c
@@ -328,10 +328,10 @@  choose_pixel_format(XMesaVisual v)
        && v->BitsPerPixel == 32) {
       if (native_byte_order) {
          /* no byteswapping needed */
-         return PIPE_FORMAT_R8G8B8A8_UNORM;
+         return PIPE_FORMAT_ABGR8888_UNORM;
       }
       else {
-         return PIPE_FORMAT_A8B8G8R8_UNORM;
+         return PIPE_FORMAT_RGBA8888_UNORM;
       }
    }
    else if (   GET_REDMASK(v)   == 0xff0000
@@ -340,10 +340,10 @@  choose_pixel_format(XMesaVisual v)
             && v->BitsPerPixel == 32) {
       if (native_byte_order) {
          /* no byteswapping needed */
-         return PIPE_FORMAT_B8G8R8A8_UNORM;
+         return PIPE_FORMAT_ARGB8888_UNORM;
       }
       else {
-         return PIPE_FORMAT_A8R8G8B8_UNORM;
+         return PIPE_FORMAT_BGRA8888_UNORM;
       }
    }
    else if (   GET_REDMASK(v)   == 0x0000ff00
@@ -352,10 +352,10 @@  choose_pixel_format(XMesaVisual v)
             && v->BitsPerPixel == 32) {
       if (native_byte_order) {
          /* no byteswapping needed */
-         return PIPE_FORMAT_A8R8G8B8_UNORM;
+         return PIPE_FORMAT_BGRA8888_UNORM;
       }
       else {
-         return PIPE_FORMAT_B8G8R8A8_UNORM;
+         return PIPE_FORMAT_ARGB8888_UNORM;
       }
    }
    else if (   GET_REDMASK(v)   == 0xf800
diff --git a/src/gallium/targets/graw-xlib/graw_xlib.c b/src/gallium/targets/graw-xlib/graw_xlib.c
index 2827747..ed112b9 100644
--- a/src/gallium/targets/graw-xlib/graw_xlib.c
+++ b/src/gallium/targets/graw-xlib/graw_xlib.c
@@ -89,13 +89,13 @@  graw_create_window_and_screen( int x,
    if (visinfo->red_mask == 0xff0000 &&
        visinfo->green_mask == 0xff00 &&
        visinfo->blue_mask == 0xff) {
-      if (format != PIPE_FORMAT_B8G8R8A8_UNORM)
+      if (format != PIPE_FORMAT_ARGB8888_UNORM)
          goto fail;
    }
    else if (visinfo->red_mask == 0xff &&
             visinfo->green_mask == 0xff00 &&
             visinfo->blue_mask == 0xff0000) {
-      if (format != PIPE_FORMAT_R8G8B8A8_UNORM)
+      if (format != PIPE_FORMAT_ABGR8888_UNORM)
          goto fail;
    }
    else {
diff --git a/src/gallium/tests/graw/clear.c b/src/gallium/tests/graw/clear.c
index 6afdf40..e591d90 100644
--- a/src/gallium/tests/graw/clear.c
+++ b/src/gallium/tests/graw/clear.c
@@ -10,8 +10,8 @@ 
 #include "pipe/p_defines.h"
 
 enum pipe_format formats[] = {
-   PIPE_FORMAT_R8G8B8A8_UNORM,
-   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_ABGR8888_UNORM,
+   PIPE_FORMAT_ARGB8888_UNORM,
    PIPE_FORMAT_NONE
 };
 
diff --git a/src/gallium/tests/graw/fs-test.c b/src/gallium/tests/graw/fs-test.c
index 685be92..b64f740 100644
--- a/src/gallium/tests/graw/fs-test.c
+++ b/src/gallium/tests/graw/fs-test.c
@@ -31,8 +31,8 @@  static void usage(char *name)
 
 
 enum pipe_format formats[] = {
-   PIPE_FORMAT_R8G8B8A8_UNORM,
-   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_ABGR8888_UNORM,
+   PIPE_FORMAT_ARGB8888_UNORM,
    PIPE_FORMAT_NONE
 };
 
diff --git a/src/gallium/tests/graw/graw_util.h b/src/gallium/tests/graw/graw_util.h
index 84456b4..d14bb89 100644
--- a/src/gallium/tests/graw/graw_util.h
+++ b/src/gallium/tests/graw/graw_util.h
@@ -32,8 +32,8 @@  graw_util_create_window(struct graw_info *info,
                         int num_cbufs, bool zstencil_buf)
 {
    static const enum pipe_format formats[] = {
-      PIPE_FORMAT_R8G8B8A8_UNORM,
-      PIPE_FORMAT_B8G8R8A8_UNORM,
+      PIPE_FORMAT_ABGR8888_UNORM,
+      PIPE_FORMAT_ARGB8888_UNORM,
       PIPE_FORMAT_NONE
    };
    enum pipe_format format;
@@ -226,7 +226,7 @@  graw_util_create_tex2d(const struct graw_info *info,
    struct pipe_box box;
 
    temp.target = PIPE_TEXTURE_2D;
-   temp.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+   temp.format = format;
    temp.width0 = width;
    temp.height0 = height;
    temp.depth0 = 1;
diff --git a/src/gallium/tests/graw/quad-sample.c b/src/gallium/tests/graw/quad-sample.c
index 9100272..004040f 100644
--- a/src/gallium/tests/graw/quad-sample.c
+++ b/src/gallium/tests/graw/quad-sample.c
@@ -18,8 +18,8 @@ 
 #include <stdio.h>
 
 enum pipe_format formats[] = {
-   PIPE_FORMAT_R8G8B8A8_UNORM,
-   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_ABGR8888_UNORM,
+   PIPE_FORMAT_ARGB8888_UNORM,
    PIPE_FORMAT_NONE
 };
 
diff --git a/src/gallium/tests/graw/shader-leak.c b/src/gallium/tests/graw/shader-leak.c
index 014e0cc..75e41e0 100644
--- a/src/gallium/tests/graw/shader-leak.c
+++ b/src/gallium/tests/graw/shader-leak.c
@@ -18,8 +18,8 @@  static int num_iters = 100;
 
 
 enum pipe_format formats[] = {
-   PIPE_FORMAT_R8G8B8A8_UNORM,
-   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_ABGR8888_UNORM,
+   PIPE_FORMAT_ARGB8888_UNORM,
    PIPE_FORMAT_NONE
 };
 
diff --git a/src/gallium/tests/graw/tri-gs.c b/src/gallium/tests/graw/tri-gs.c
index 535825e..21a3a97 100644
--- a/src/gallium/tests/graw/tri-gs.c
+++ b/src/gallium/tests/graw/tri-gs.c
@@ -14,8 +14,8 @@ 
 #include "util/u_inlines.h"
 
 enum pipe_format formats[] = {
-   PIPE_FORMAT_R8G8B8A8_UNORM,
-   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_ABGR8888_UNORM,
+   PIPE_FORMAT_ARGB8888_UNORM,
    PIPE_FORMAT_NONE
 };
 
diff --git a/src/gallium/tests/graw/tri-instanced.c b/src/gallium/tests/graw/tri-instanced.c
index d00e7e9..c8407f6 100644
--- a/src/gallium/tests/graw/tri-instanced.c
+++ b/src/gallium/tests/graw/tri-instanced.c
@@ -17,8 +17,8 @@ 
 
 
 enum pipe_format formats[] = {
-   PIPE_FORMAT_R8G8B8A8_UNORM,
-   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_ABGR8888_UNORM,
+   PIPE_FORMAT_ARGB8888_UNORM,
    PIPE_FORMAT_NONE
 };
 
diff --git a/src/gallium/tests/graw/vs-test.c b/src/gallium/tests/graw/vs-test.c
index bfb40be..6d66d1f 100644
--- a/src/gallium/tests/graw/vs-test.c
+++ b/src/gallium/tests/graw/vs-test.c
@@ -32,8 +32,8 @@  static void usage(char *name)
 
 
 enum pipe_format formats[] = {
-   PIPE_FORMAT_R8G8B8A8_UNORM,
-   PIPE_FORMAT_B8G8R8A8_UNORM,
+   PIPE_FORMAT_ABGR8888_UNORM,
+   PIPE_FORMAT_ARGB8888_UNORM,
    PIPE_FORMAT_NONE
 };
 
diff --git a/src/mesa/state_tracker/st_format.c b/src/mesa/state_tracker/st_format.c
index 56f3a4a..ae9e28e 100644
--- a/src/mesa/state_tracker/st_format.c
+++ b/src/mesa/state_tracker/st_format.c
@@ -55,21 +55,21 @@  st_mesa_format_to_pipe_format(gl_format mesaFormat)
 {
    switch (mesaFormat) {
    case MESA_FORMAT_RGBA8888:
-      return PIPE_FORMAT_A8B8G8R8_UNORM;
+      return PIPE_FORMAT_RGBA8888_UNORM;
    case MESA_FORMAT_RGBA8888_REV:
-      return PIPE_FORMAT_R8G8B8A8_UNORM;
+      return PIPE_FORMAT_ABGR8888_UNORM;
    case MESA_FORMAT_ARGB8888:
-      return PIPE_FORMAT_B8G8R8A8_UNORM;
+      return PIPE_FORMAT_ARGB8888_UNORM;
    case MESA_FORMAT_ARGB8888_REV:
-      return PIPE_FORMAT_A8R8G8B8_UNORM;
+      return PIPE_FORMAT_BGRA8888_UNORM;
    case MESA_FORMAT_RGBX8888:
-      return PIPE_FORMAT_X8B8G8R8_UNORM;
+      return PIPE_FORMAT_RGBX8888_UNORM;
    case MESA_FORMAT_RGBX8888_REV:
-      return PIPE_FORMAT_R8G8B8X8_UNORM;
+      return PIPE_FORMAT_XBGR8888_UNORM;
    case MESA_FORMAT_XRGB8888:
-      return PIPE_FORMAT_B8G8R8X8_UNORM;
+      return PIPE_FORMAT_XRGB8888_UNORM;
    case MESA_FORMAT_XRGB8888_REV:
-      return PIPE_FORMAT_X8R8G8B8_UNORM;
+      return PIPE_FORMAT_BGRX8888_UNORM;
    case MESA_FORMAT_ARGB1555:
       return PIPE_FORMAT_B5G5R5A1_UNORM;
    case MESA_FORMAT_ARGB4444:
@@ -401,21 +401,21 @@  gl_format
 st_pipe_format_to_mesa_format(enum pipe_format format)
 {
    switch (format) {
-   case PIPE_FORMAT_A8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBA8888_UNORM:
       return MESA_FORMAT_RGBA8888;
-   case PIPE_FORMAT_R8G8B8A8_UNORM:
+   case PIPE_FORMAT_ABGR8888_UNORM:
       return MESA_FORMAT_RGBA8888_REV;
-   case PIPE_FORMAT_B8G8R8A8_UNORM:
+   case PIPE_FORMAT_ARGB8888_UNORM:
       return MESA_FORMAT_ARGB8888;
-   case PIPE_FORMAT_A8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRA8888_UNORM:
       return MESA_FORMAT_ARGB8888_REV;
-   case PIPE_FORMAT_X8B8G8R8_UNORM:
+   case PIPE_FORMAT_RGBX8888_UNORM:
       return MESA_FORMAT_RGBX8888;
-   case PIPE_FORMAT_R8G8B8X8_UNORM:
+   case PIPE_FORMAT_XBGR8888_UNORM:
       return MESA_FORMAT_RGBX8888_REV;
-   case PIPE_FORMAT_B8G8R8X8_UNORM:
+   case PIPE_FORMAT_XRGB8888_UNORM:
       return MESA_FORMAT_XRGB8888;
-   case PIPE_FORMAT_X8R8G8B8_UNORM:
+   case PIPE_FORMAT_BGRX8888_UNORM:
       return MESA_FORMAT_XRGB8888_REV;
    case PIPE_FORMAT_B5G5R5A1_UNORM:
       return MESA_FORMAT_ARGB1555;
@@ -1521,12 +1521,12 @@  struct exact_format_mapping
 
 static const struct exact_format_mapping rgba8888_tbl[] =
 {
-   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_A8B8G8R8_UNORM },
-   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_A8B8G8R8_UNORM },
-   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_R8G8B8A8_UNORM },
-   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_R8G8B8A8_UNORM },
-   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_A8R8G8B8_UNORM },
-   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_B8G8R8A8_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_RGBA8888_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_RGBA8888_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_ABGR8888_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_ABGR8888_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_BGRA8888_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_ARGB8888_UNORM },
    { GL_RGBA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_R8G8B8A8_UNORM },
    { GL_ABGR_EXT, GL_UNSIGNED_BYTE,               PIPE_FORMAT_A8B8G8R8_UNORM },
    { GL_BGRA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_B8G8R8A8_UNORM },
@@ -1535,15 +1535,15 @@  static const struct exact_format_mapping rgba8888_tbl[] =
 
 static const struct exact_format_mapping rgbx8888_tbl[] =
 {
-   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_X8R8G8B8_UNORM },
-   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_B8G8R8X8_UNORM },
-   { GL_BGRA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_B8G8R8X8_UNORM },
-   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_X8B8G8R8_UNORM },
-   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_X8B8G8R8_UNORM },
-   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_R8G8B8X8_UNORM },
-   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_R8G8B8X8_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_RGBX8888_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_RGBX8888_UNORM },
+   { GL_RGBA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_XBGR8888_UNORM },
+   { GL_ABGR_EXT, GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_XBGR8888_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8,        PIPE_FORMAT_BGRX8888_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_INT_8_8_8_8_REV,    PIPE_FORMAT_XRGB8888_UNORM },
    { GL_RGBA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_R8G8B8X8_UNORM },
    { GL_ABGR_EXT, GL_UNSIGNED_BYTE,               PIPE_FORMAT_X8B8G8R8_UNORM },
+   { GL_BGRA,     GL_UNSIGNED_BYTE,               PIPE_FORMAT_B8G8R8X8_UNORM },
    { 0,           0,                              0                          }
 };
 
diff -up mesa-20130610/src/gallium/drivers/r600/evergreen_state.c.jx mesa-20130610/src/gallium/drivers/r600/evergreen_state.c
--- mesa-20130610/src/gallium/drivers/r600/evergreen_state.c.jx	2013-06-10 13:58:51.000000000 -0400
+++ mesa-20130610/src/gallium/drivers/r600/evergreen_state.c	2013-06-17 10:24:14.687160428 -0400
@@ -615,7 +615,7 @@  static uint32_t r600_translate_colorform
 
 static uint32_t r600_colorformat_endian_swap(uint32_t colorformat)
 {
-	if (R600_BIG_ENDIAN) {
+	if (0 && R600_BIG_ENDIAN) {
 		switch(colorformat) {
 
 		/* 8-bit buffers. */

Comments

On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
> On 10.03.2014 02:49, Michel Dänzer wrote:
> >
> > Congratulations, you just broke llvmpipe again on big endian systems. ;)
> I'm sorry but Mesa classic works very well on Debian Sid and Lubuntu 
> 14.04 with these changes. ;) Why does Mesa classic work with the 
> little-endian defines?

What do you mean by 'Mesa classic'? The r600g driver works with the
little endian defines because r600g assumes st/mesa uses the formats the
way it did before the llvmpipe big endian fixes.


> > Did you even look at the commits introducing those defines? Did you
> > really think those defines, with explicit endianness checks, were
> > introduced for no reason but to break drivers on big endian systems?
> >
> >
> > I explained the problem in r600g and how it could be solved. Please
> > explore that.
> I'll try to explore that but I don't have any knowledge about the Mesa 
> source code. The Fedora guys have solved the problem with the patch 
> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?

It sounds like an older downstream attempt at fixing llvmpipe on big
endian hosts, which was superseded by the upstream fixes, which were
incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
Richard Sandiford (the author of the fixes) to CC, maybe they can help
you fix up r600g.
Michel Dänzer <michel@daenzer.net> writes:
> On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
>> On 10.03.2014 02:49, Michel Dänzer wrote:
>> >
>> > Congratulations, you just broke llvmpipe again on big endian systems. ;)
>> I'm sorry but Mesa classic works very well on Debian Sid and Lubuntu 
>> 14.04 with these changes. ;) Why does Mesa classic work with the 
>> little-endian defines?
>
> What do you mean by 'Mesa classic'? The r600g driver works with the
> little endian defines because r600g assumes st/mesa uses the formats the
> way it did before the llvmpipe big endian fixes.
>
>> > Did you even look at the commits introducing those defines? Did you
>> > really think those defines, with explicit endianness checks, were
>> > introduced for no reason but to break drivers on big endian systems?
>> >
>> >
>> > I explained the problem in r600g and how it could be solved. Please
>> > explore that.
>> I'll try to explore that but I don't have any knowledge about the Mesa 
>> source code. The Fedora guys have solved the problem with the patch 
>> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?
>
> It sounds like an older downstream attempt at fixing llvmpipe on big
> endian hosts, which was superseded by the upstream fixes, which were
> incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
> Richard Sandiford (the author of the fixes) to CC, maybe they can help
> you fix up r600g.

I don't know the r600 code at all, sorry.  But like you say, if the code
is treating the x8y8z8w8 formats as low-to-high integers (x in lsb, z in msb)
then the right fix should be to use PIPE_FORMAT_xyzw8888_* instead of
PIPE_FORMAT_x8y8z8w8_*.

Thanks,
Richard
Am 11.03.14 12:08, schrieb Richard Sandiford:
> Michel Dänzer <michel@daenzer.net> writes:
>> On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
>>> On 10.03.2014 02:49, Michel Dänzer wrote:
>>>> Congratulations, you just broke llvmpipe again on big endian systems. ;)
>>> I'm sorry but Mesa classic works very well on Debian Sid and Lubuntu
>>> 14.04 with these changes. ;) Why does Mesa classic work with the
>>> little-endian defines?
>> What do you mean by 'Mesa classic'? The r600g driver works with the
>> little endian defines because r600g assumes st/mesa uses the formats the
>> way it did before the llvmpipe big endian fixes.
>>
>>>> Did you even look at the commits introducing those defines? Did you
>>>> really think those defines, with explicit endianness checks, were
>>>> introduced for no reason but to break drivers on big endian systems?
>>>>
>>>>
>>>> I explained the problem in r600g and how it could be solved. Please
>>>> explore that.
>>> I'll try to explore that but I don't have any knowledge about the Mesa
>>> source code. The Fedora guys have solved the problem with the patch
>>> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?
>> It sounds like an older downstream attempt at fixing llvmpipe on big
>> endian hosts, which was superseded by the upstream fixes, which were
>> incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
>> Richard Sandiford (the author of the fixes) to CC, maybe they can help
>> you fix up r600g.
> I don't know the r600 code at all, sorry.  But like you say, if the code
> is treating the x8y8z8w8 formats as low-to-high integers (x in lsb, z in msb)
> then the right fix should be to use PIPE_FORMAT_xyzw8888_* instead of
> PIPE_FORMAT_x8y8z8w8_*.
>
> Thanks,
> Richard
>
>
Richard,

How can I change the formats x8y8z8w8 to xyzw8888?

Cheers,
Christian
Christian Zigotzky <chzigotzky@xenosoft.de> writes:
> Am 11.03.14 12:08, schrieb Richard Sandiford:
>> Michel Dänzer <michel@daenzer.net> writes:
>>> On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
>>>> On 10.03.2014 02:49, Michel Dänzer wrote:
>>>>> Congratulations, you just broke llvmpipe again on big endian systems. ;)
>>>> I'm sorry but Mesa classic works very well on Debian Sid and Lubuntu
>>>> 14.04 with these changes. ;) Why does Mesa classic work with the
>>>> little-endian defines?
>>> What do you mean by 'Mesa classic'? The r600g driver works with the
>>> little endian defines because r600g assumes st/mesa uses the formats the
>>> way it did before the llvmpipe big endian fixes.
>>>
>>>>> Did you even look at the commits introducing those defines? Did you
>>>>> really think those defines, with explicit endianness checks, were
>>>>> introduced for no reason but to break drivers on big endian systems?
>>>>>
>>>>>
>>>>> I explained the problem in r600g and how it could be solved. Please
>>>>> explore that.
>>>> I'll try to explore that but I don't have any knowledge about the Mesa
>>>> source code. The Fedora guys have solved the problem with the patch
>>>> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?
>>> It sounds like an older downstream attempt at fixing llvmpipe on big
>>> endian hosts, which was superseded by the upstream fixes, which were
>>> incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
>>> Richard Sandiford (the author of the fixes) to CC, maybe they can help
>>> you fix up r600g.
>> I don't know the r600 code at all, sorry.  But like you say, if the code
>> is treating the x8y8z8w8 formats as low-to-high integers (x in lsb, z in msb)
>> then the right fix should be to use PIPE_FORMAT_xyzw8888_* instead of
>> PIPE_FORMAT_x8y8z8w8_*.
>>
>> Thanks,
>> Richard
>>
>>
> Richard,
>
> How can I change the formats x8y8z8w8 to xyzw8888?

I just mean changing instances of things like PIPE_FORMAT_A8R8G8B8_UNORM
to PIPE_FORMAT_ARGB8888_UNORM in the relevant parts of the r600 support
(which is I think what Michel also meant -- like I say, I'm not really
adding anything new here).  PIPE_FORMAT_ARGB8888_UNORM always has the
alpha channel in the low bits of a 32-bit int according to host endianness,
whereas PIPE_FORMAT_A8R8G8B8_UNORM always has the alpha channel in the
first byte of memory.

I can't say for sure which the "revelavant parts" are because I don't
know the r600 code.

Thanks,
Richard
Am 11.03.14 16:25, schrieb Richard Sandiford:
> Christian Zigotzky <chzigotzky@xenosoft.de> writes:
>> Am 11.03.14 12:08, schrieb Richard Sandiford:
>>> Michel Dänzer <michel@daenzer.net> writes:
>>>> On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
>>>>> On 10.03.2014 02:49, Michel Dänzer wrote:
>>>>>> Congratulations, you just broke llvmpipe again on big endian systems. ;)
>>>>> I'm sorry but Mesa classic works very well on Debian Sid and Lubuntu
>>>>> 14.04 with these changes. ;) Why does Mesa classic work with the
>>>>> little-endian defines?
>>>> What do you mean by 'Mesa classic'? The r600g driver works with the
>>>> little endian defines because r600g assumes st/mesa uses the formats the
>>>> way it did before the llvmpipe big endian fixes.
>>>>
>>>>>> Did you even look at the commits introducing those defines? Did you
>>>>>> really think those defines, with explicit endianness checks, were
>>>>>> introduced for no reason but to break drivers on big endian systems?
>>>>>>
>>>>>>
>>>>>> I explained the problem in r600g and how it could be solved. Please
>>>>>> explore that.
>>>>> I'll try to explore that but I don't have any knowledge about the Mesa
>>>>> source code. The Fedora guys have solved the problem with the patch
>>>>> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?
>>>> It sounds like an older downstream attempt at fixing llvmpipe on big
>>>> endian hosts, which was superseded by the upstream fixes, which were
>>>> incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
>>>> Richard Sandiford (the author of the fixes) to CC, maybe they can help
>>>> you fix up r600g.
>>> I don't know the r600 code at all, sorry.  But like you say, if the code
>>> is treating the x8y8z8w8 formats as low-to-high integers (x in lsb, z in msb)
>>> then the right fix should be to use PIPE_FORMAT_xyzw8888_* instead of
>>> PIPE_FORMAT_x8y8z8w8_*.
>>>
>>> Thanks,
>>> Richard
>>>
>>>
>> Richard,
>>
>> How can I change the formats x8y8z8w8 to xyzw8888?
> I just mean changing instances of things like PIPE_FORMAT_A8R8G8B8_UNORM
> to PIPE_FORMAT_ARGB8888_UNORM in the relevant parts of the r600 support
> (which is I think what Michel also meant -- like I say, I'm not really
> adding anything new here).  PIPE_FORMAT_ARGB8888_UNORM always has the
> alpha channel in the low bits of a 32-bit int according to host endianness,
> whereas PIPE_FORMAT_A8R8G8B8_UNORM always has the alpha channel in the
> first byte of memory.
>
> I can't say for sure which the "revelavant parts" are because I don't
> know the r600 code.
>
> Thanks,
> Richard
>
>
Thanks a lot for your answer. I've found PIPE_FORMAT_A8R8G8B8_UNORM in 
the files r600_state.c and evergreen_state.c. I'm going to change these 
to PIPE_FORMAT_ARGB8888_UNORM.

--Christian
On 11.03.2014 16:25, Richard Sandiford wrote:
> I just mean changing instances of things like PIPE_FORMAT_A8R8G8B8_UNORM
> to PIPE_FORMAT_ARGB8888_UNORM in the relevant parts of the r600 support
> (which is I think what Michel also meant -- like I say, I'm not really
> adding anything new here).  PIPE_FORMAT_ARGB8888_UNORM always has the
> alpha channel in the low bits of a 32-bit int according to host endianness,
> whereas PIPE_FORMAT_A8R8G8B8_UNORM always has the alpha channel in the
> first byte of memory.
>
> I can't say for sure which the "revelavant parts" are because I don't
> know the r600 code.
>
> Thanks,
> Richard
>
>
I have replaced PIPE_FORMAT_A8R8G8B8_UNORM with 
PIPE_FORMAT_ARGB8888_UNORM in the files r600_state.c and 
evergreen_state.c. But I get the following error:

make[3]: Entering directory 
`/home/christian/Downloads/Mesa-10.1.0/src/gallium/drivers/r600'
   CC       r600_state.lo
r600_state.c: In function 'r600_translate_colorswap':
r600_state.c:262:2: error: duplicate case value
r600_state.c:258:2: error: previously used here
r600_state.c: In function 'r600_translate_colorformat':
r600_state.c:427:2: error: duplicate case value
r600_state.c:425:2: error: previously used here
make[3]: *** [r600_state.lo] Fehler 1
make[3]: Leaving directory 
`/home/christian/Downloads/Mesa-10.1.0/src/gallium/drivers/r600'
make[2]: *** [all-recursive] Fehler 1
make[2]: Leaving directory 
`/home/christian/Downloads/Mesa-10.1.0/src/gallium/drivers'
make[1]: *** [all-recursive] Fehler 1
make[1]: Leaving directory `/home/christian/Downloads/Mesa-10.1.0/src'
make: *** [all-recursive] Fehler 1
On Die, 2014-03-11 at 11:08 +0000, Richard Sandiford wrote:
> Michel Dänzer <michel@daenzer.net> writes:
> > On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
> >> 
> >> The Fedora guys have solved the problem with the patch 
> >> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?
> >
> > It sounds like an older downstream attempt at fixing llvmpipe on big
> > endian hosts, which was superseded by the upstream fixes, which were
> > incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
> > Richard Sandiford (the author of the fixes) to CC, maybe they can help
> > you fix up r600g.
> 
> I don't know the r600 code at all, sorry.

Fair enough, but still I'm starting to regret that I didn't ask you guys
to at least try working with others to get the hardware drivers fixed up
for the llvmpipe big endian fixes before pushing them...

Also, I was hoping there would be followup work extending the same
approach for the remaining formats. Do you have any plans for that? The
current half-finished situation is quite messy and confusing for people
working on format related code.
Michel Dänzer <michel@daenzer.net> writes:
> On Die, 2014-03-11 at 11:08 +0000, Richard Sandiford wrote:
>> Michel Dänzer <michel@daenzer.net> writes:
>> > On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
>> >> 
>> >> The Fedora guys have solved the problem with the patch 
>> >> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?
>> >
>> > It sounds like an older downstream attempt at fixing llvmpipe on big
>> > endian hosts, which was superseded by the upstream fixes, which were
>> > incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
>> > Richard Sandiford (the author of the fixes) to CC, maybe they can help
>> > you fix up r600g.
>> 
>> I don't know the r600 code at all, sorry.
>
> Fair enough, but still I'm starting to regret that I didn't ask you guys
> to at least try working with others to get the hardware drivers fixed up
> for the llvmpipe big endian fixes before pushing them...
>
> Also, I was hoping there would be followup work extending the same
> approach for the remaining formats. Do you have any plans for that? The
> current half-finished situation is quite messy and confusing for people
> working on format related code.

I started down that route with the patch attached to:

   http://lists.freedesktop.org/archives/mesa-dev/2013-June/040594.html

It depended on those 8 patches being applied first, but although the
series got positive feedback, it didn't really go anywhere beyond that.
I suppose I should have pushed for someone to apply it.

I'm happy to retest and repost the series if someone would be willing
to put it in.  I can then go through the other patches I have locally
that were held up on those.  But (obviously) I'm not anything like a
frequent-enough contributor for commit access to make sense.

Thanks,
Richard
On Mit, 2014-03-12 at 11:26 +0000, Richard Sandiford wrote:
> Michel Dänzer <michel@daenzer.net> writes:
> > On Die, 2014-03-11 at 11:08 +0000, Richard Sandiford wrote:
> >> Michel Dänzer <michel@daenzer.net> writes:
> >> > On Mon, 2014-03-10 at 10:11 +0100, Christian Zigotzky wrote:
> >> >> 
> >> >> The Fedora guys have solved the problem with the patch 
> >> >> "mesa-9.2-llvmpipe-on-big-endian.patch". What do you think of this patch?
> >> >
> >> > It sounds like an older downstream attempt at fixing llvmpipe on big
> >> > endian hosts, which was superseded by the upstream fixes, which were
> >> > incidentally pushed by the 'Fedora guy' Adam Jackson. Adding him and
> >> > Richard Sandiford (the author of the fixes) to CC, maybe they can help
> >> > you fix up r600g.
> >> 
> >> I don't know the r600 code at all, sorry.
> >
> > Fair enough, but still I'm starting to regret that I didn't ask you guys
> > to at least try working with others to get the hardware drivers fixed up
> > for the llvmpipe big endian fixes before pushing them...
> >
> > Also, I was hoping there would be followup work extending the same
> > approach for the remaining formats. Do you have any plans for that? The
> > current half-finished situation is quite messy and confusing for people
> > working on format related code.
> 
> I started down that route with the patch attached to:
> 
>    http://lists.freedesktop.org/archives/mesa-dev/2013-June/040594.html
> 
> It depended on those 8 patches being applied first, but although the
> series got positive feedback, it didn't really go anywhere beyond that.
> I suppose I should have pushed for someone to apply it.
> 
> I'm happy to retest and repost the series if someone would be willing
> to put it in.

Yes, please work with José on getting this in.