summaryrefslogtreecommitdiffstats
path: root/src/gallium/auxiliary
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/auxiliary')
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_conv.c76
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_conv.h11
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_aos.c31
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_aos_array.c56
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_soa.c21
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_format_yuv.c2
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_gather.c25
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_gather.h6
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_sample_aos.c4
-rw-r--r--src/gallium/auxiliary/gallivm/lp_bld_swizzle.c80
-rw-r--r--src/gallium/auxiliary/util/u_format.h25
-rw-r--r--src/gallium/auxiliary/util/u_format_pack.py29
-rwxr-xr-xsrc/gallium/auxiliary/util/u_format_parse.py10
-rwxr-xr-xsrc/gallium/auxiliary/util/u_format_table.py4
-rw-r--r--src/gallium/auxiliary/util/u_pack_color.h36
15 files changed, 160 insertions, 256 deletions
diff --git a/src/gallium/auxiliary/gallivm/lp_bld_conv.c b/src/gallium/auxiliary/gallivm/lp_bld_conv.c
index f11361ac06b..cbea966882a 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 d7dfed85187..42a11137473 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 6a1bf6765d7..af755d460c1 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 3402a0b1530..ee3ca86c000 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 edc24424289..4c6bd81047a 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 e542abce0cc..873f354c040 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 eefb23a946f..9155d811c06 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 8e4c07d82b8..ee694732d36 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 c31b05d7022..104c24d83b9 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 08d817a28f5..79116bcf391 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 4cace6ad1b9..9774a2b4c82 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 565d059c3e3..d1f68c80422 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 07052b99666..e202099b9ef 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 8edb505237d..9d44cf3914b 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 1f6a56a336d..102ad60517f 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_ABGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
}
return;
- case PIPE_FORMAT_X8B8G8R8_UNORM:
+ case PIPE_FORMAT_XBGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
}
return;
- case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_BGRA8888_UNORM:
{
uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
}
return;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_BGRX8888_UNORM:
{
uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
}
return;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_ARGB8888_UNORM:
{
uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
}
return;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_XRGB8888_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_ABGR8888_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_XBGR8888_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_BGRA8888_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_BGRX8888_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_ARGB8888_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_XRGB8888_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_ABGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | a;
}
return;
- case PIPE_FORMAT_X8B8G8R8_UNORM:
+ case PIPE_FORMAT_XBGR8888_UNORM:
{
uc->ui = (r << 24) | (g << 16) | (b << 8) | 0xff;
}
return;
- case PIPE_FORMAT_B8G8R8A8_UNORM:
+ case PIPE_FORMAT_BGRA8888_UNORM:
{
uc->ui = (a << 24) | (r << 16) | (g << 8) | b;
}
return;
- case PIPE_FORMAT_B8G8R8X8_UNORM:
+ case PIPE_FORMAT_BGRX8888_UNORM:
{
uc->ui = (0xff << 24) | (r << 16) | (g << 8) | b;
}
return;
- case PIPE_FORMAT_A8R8G8B8_UNORM:
+ case PIPE_FORMAT_ARGB8888_UNORM:
{
uc->ui = (b << 24) | (g << 16) | (r << 8) | a;
}
return;
- case PIPE_FORMAT_X8R8G8B8_UNORM:
+ case PIPE_FORMAT_XRGB8888_UNORM:
{
uc->ui = (b << 24) | (g << 16) | (r << 8) | 0xff;
}