summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAdhemerval Zanella <[email protected]>2013-01-20 11:42:16 -0600
committerAdam Jackson <[email protected]>2013-02-11 13:41:28 -0500
commit1ab2c55bf49dd90e1c08e0b8226e354137d041cd (patch)
tree9852015597cc2cf71bc8a7c95288fb6619061462 /src
parenta8016b2f607ce8921972acb6ee6723c5a2d54017 (diff)
llvmpipe: fix vertex_header mask store in big-endian
This patch fixes the vertex_header mask bitfield store in big-endian architectures by bit-swap the fields accordingly. Reviewed-by: Adam Jackson <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm.c48
1 files changed, 48 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c
index dc83f805a0f..f3bbbbb0ace 100644
--- a/src/gallium/auxiliary/draw/draw_llvm.c
+++ b/src/gallium/auxiliary/draw/draw_llvm.c
@@ -646,6 +646,53 @@ store_aos(struct gallivm_state *gallivm,
lp_set_store_alignment(LLVMBuildStore(builder, value, data_ptr), sizeof(float));
}
+/**
+ * Adjust the mask to architecture endianess. The mask will the store in struct:
+ *
+ * struct vertex_header {
+ * unsigned clipmask:DRAW_TOTAL_CLIP_PLANES;
+ * unsigned edgeflag:1;
+ * unsigned have_clipdist:1;
+ * unsigned vertex_id:16;
+ * [...]
+ * }
+ *
+ * On little-endian machine nothing needs to done, however on bit-endian machine
+ * the mask's fields need to be adjusted with the algorithm:
+ *
+ * uint32_t reverse (uint32_t x)
+ * {
+ * return (x >> 16) | // vertex_id
+ * ((x & 0x3fff) << 18) | // clipmask
+ * ((x & 0x4000) << 3) | // have_clipdist
+ * ((x & 0x8000) << 1); // edgeflag
+ * }
+ */
+static LLVMValueRef
+adjust_mask(struct gallivm_state *gallivm,
+ LLVMValueRef mask)
+{
+#ifdef PIPE_ARCH_BIG_ENDIAN
+ LLVMBuilderRef builder = gallivm->builder;
+ LLVMValueRef vertex_id;
+ LLVMValueRef clipmask;
+ LLVMValueRef have_clipdist;
+ LLVMValueRef edgeflag;
+
+ vertex_id = LLVMBuildLShr(builder, mask, lp_build_const_int32(gallivm, 16), "");
+ clipmask = LLVMBuildAnd(builder, mask, lp_build_const_int32(gallivm, 0x3fff), "");
+ clipmask = LLVMBuildShl(builder, clipmask, lp_build_const_int32(gallivm, 18), "");
+ have_clipdist = LLVMBuildAnd(builder, mask, lp_build_const_int32(gallivm, 0x4000), "");
+ have_clipdist = LLVMBuildShl(builder, have_clipdist, lp_build_const_int32(gallivm, 3), "");
+ edgeflag = LLVMBuildAnd(builder, mask, lp_build_const_int32(gallivm, 0x8000), "");
+ edgeflag = LLVMBuildShl(builder, edgeflag, lp_build_const_int32(gallivm, 1), "");
+
+ mask = LLVMBuildOr(builder, vertex_id, clipmask, "");
+ mask = LLVMBuildOr(builder, mask, have_clipdist, "");
+ mask = LLVMBuildOr(builder, mask, edgeflag, "");
+#endif
+ return mask;
+}
static void
store_aos_array(struct gallivm_state *gallivm,
@@ -690,6 +737,7 @@ store_aos_array(struct gallivm_state *gallivm,
for (i = 0; i < vector_length; i++) {
LLVMValueRef id_ptr = draw_jit_header_id(gallivm, io_ptrs[i]);
val = LLVMBuildExtractElement(builder, cliptmp, inds[i], "");
+ val = adjust_mask(gallivm, val);
LLVMBuildStore(builder, val, id_ptr);
#if DEBUG_STORE
lp_build_printf(gallivm, "io = %p, index %d\n, clipmask = %x\n",