diff options
author | Adhemerval Zanella <[email protected]> | 2013-01-20 11:42:16 -0600 |
---|---|---|
committer | Adam Jackson <[email protected]> | 2013-02-11 13:41:28 -0500 |
commit | 1ab2c55bf49dd90e1c08e0b8226e354137d041cd (patch) | |
tree | 9852015597cc2cf71bc8a7c95288fb6619061462 /src | |
parent | a8016b2f607ce8921972acb6ee6723c5a2d54017 (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.c | 48 |
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", |