summaryrefslogtreecommitdiff
path: root/src/gallium/auxiliary/draw/draw_llvm_translate.c
diff options
context:
space:
mode:
authorZack Rusin <zackr@vmware.com>2010-02-22 22:02:58 -0500
committerZack Rusin <zackr@vmware.com>2010-02-22 22:02:58 -0500
commitc5c5cd7132e18f4aad8e73d8ee879f8823c4c1e7 (patch)
treef36680fba5d44945075e4b6f7d4269154b3c1e7d /src/gallium/auxiliary/draw/draw_llvm_translate.c
parent902ccfcb40f21e1a5fca2f1bec1cbbabb053d8cf (diff)
gallium/draw: initial code to properly support llvm in the draw module
code generate big chunks of the vertex pipeline in order to speed up software vertex processing.
Diffstat (limited to 'src/gallium/auxiliary/draw/draw_llvm_translate.c')
-rw-r--r--src/gallium/auxiliary/draw/draw_llvm_translate.c653
1 files changed, 653 insertions, 0 deletions
diff --git a/src/gallium/auxiliary/draw/draw_llvm_translate.c b/src/gallium/auxiliary/draw/draw_llvm_translate.c
new file mode 100644
index 0000000000..588e97b29c
--- /dev/null
+++ b/src/gallium/auxiliary/draw/draw_llvm_translate.c
@@ -0,0 +1,653 @@
+
+
+
+#include "util/u_memory.h"
+#include "pipe/p_state.h"
+#include "translate.h"
+
+
+#define DRAW_DBG 0
+
+typedef void (*fetch_func)(const void *ptr, float *attrib);
+typedef void (*emit_func)(const float *attrib, void *ptr);
+
+
+
+struct translate_generic {
+ struct translate translate;
+
+ struct {
+ enum translate_element_type type;
+
+ fetch_func fetch;
+ unsigned buffer;
+ unsigned input_offset;
+ unsigned instance_divisor;
+
+ emit_func emit;
+ unsigned output_offset;
+
+ char *input_ptr;
+ unsigned input_stride;
+
+ } attrib[PIPE_MAX_ATTRIBS];
+
+ unsigned nr_attrib;
+};
+
+
+static struct translate_generic *translate_generic( struct translate *translate )
+{
+ return (struct translate_generic *)translate;
+}
+
+/**
+ * Fetch a float[4] vertex attribute from memory, doing format/type
+ * conversion as needed.
+ *
+ * This is probably needed/dupliocated elsewhere, eg format
+ * conversion, texture sampling etc.
+ */
+#define ATTRIB( NAME, SZ, TYPE, FROM, TO ) \
+static void \
+fetch_##NAME(const void *ptr, float *attrib) \
+{ \
+ const float defaults[4] = { 0.0f,0.0f,0.0f,1.0f }; \
+ unsigned i; \
+ \
+ for (i = 0; i < SZ; i++) { \
+ attrib[i] = FROM(i); \
+ } \
+ \
+ for (; i < 4; i++) { \
+ attrib[i] = defaults[i]; \
+ } \
+} \
+ \
+static void \
+emit_##NAME(const float *attrib, void *ptr) \
+{ \
+ unsigned i; \
+ TYPE *out = (TYPE *)ptr; \
+ \
+ for (i = 0; i < SZ; i++) { \
+ out[i] = TO(attrib[i]); \
+ } \
+}
+
+{
+
+ return conv = instr(builder, bc, "");
+}
+
+static INLINE LLVMValueRef
+from_64_float(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMDoubleType() , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ return LLVMBuildFPTrunc(builder, l, LLVMFloatType(), "");
+}
+
+static INLINE LLVMValueRef
+from_32_float(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMFloatType() , "");
+ return LLVMBuildLoad(builder, bc, "");
+}
+
+static INLINE LLVMValueRef
+from_8_uscaled(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, val, "");
+ return LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
+}
+
+static INLINE LLVMValueRef
+from_16_uscaled(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(16) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ return LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
+}
+
+static INLINE LLVMValueRef
+from_32_uscaled(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(32) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ return LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
+}
+
+static INLINE LLVMValueRef
+from_8_sscaled(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, val, "");
+ return LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
+}
+
+static INLINE LLVMValueRef
+from_16_sscaled(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(16) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ return LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
+}
+
+static INLINE LLVMValueRef
+from_32_sscaled(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(32) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ return LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
+}
+
+
+static INLINE LLVMValueRef
+from_8_unorm(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, val, "");
+ LLVMValueRef uscaled = LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
+ return LLVMBuildFDiv(builder, uscaled,
+ LLVMConstReal(builder, 255.));
+}
+
+static INLINE LLVMValueRef
+from_16_unorm(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(16) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ LLVMValueRef uscaled = LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
+ return LLVMBuildFDiv(builder, uscaled,
+ LLVMConstReal(builder, 65535.));
+}
+
+static INLINE LLVMValueRef
+from_32_unorm(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(32) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ LLVMValueRef uscaled = LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
+
+ return LLVMBuildFDiv(builder, uscaled,
+ LLVMConstReal(builder, 4294967295.));
+}
+
+static INLINE LLVMValueRef
+from_8_snorm(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, val, "");
+ LLVMValueRef uscaled = LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
+ return LLVMBuildFDiv(builder, uscaled,
+ LLVMConstReal(builder, 127.0));
+}
+
+static INLINE LLVMValueRef
+from_16_snorm(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(16) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ LLVMValueRef uscaled = LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
+ return LLVMBuildFDiv(builder, uscaled,
+ LLVMConstReal(builder, 32767.0f));
+}
+
+static INLINE LLVMValueRef
+from_32_snorm(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(32) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ LLVMValueRef uscaled = LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
+
+ return LLVMBuildFDiv(builder, uscaled,
+ LLVMConstReal(builder, 2147483647.0));
+}
+
+static INLINE LLVMValueRef
+from_32_fixed(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef bc = LLVMBuildBitCast(builder, val,
+ LLVMIntType(32) , "");
+ LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
+ LLVMValueRef uscaled = LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
+
+ return LLVMBuildFDiv(builder, uscaled,
+ LLVMConstReal(builder, 65536.0));
+}
+
+static INLINE LLVMValueRef
+to_64_float(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ return LLVMBuildFPExt(builder, l, LLVMDoubleType(), "");
+}
+
+static INLINE LLVMValueRef
+to_32_float(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ return LLVMBuildLoad(builder, fp, "");
+}
+
+atic INLINE LLVMValueRef
+to_8_uscaled(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ return LLVMBuildFPToUI(builder, l, LLVMIntType(8), "");
+}
+
+static INLINE LLVMValueRef
+to_16_uscaled(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ return LLVMBuildFPToUI(builder, l, LLVMIntType(16), "");
+}
+
+static INLINE LLVMValueRef
+to_32_uscaled(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ return LLVMBuildFPToUI(builder, l, LLVMIntType(32), "");
+}
+
+static INLINE LLVMValueRef
+to_8_sscaled(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ return LLVMBuildFPToSI(builder, l, LLVMIntType(8), "");
+}
+
+static INLINE LLVMValueRef
+to_16_sscaled(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ return LLVMBuildFPToSI(builder, l, LLVMIntType(16), "");
+}
+
+static INLINE LLVMValueRef
+to_32_sscaled(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ return LLVMBuildFPToSI(builder, l, LLVMIntType(32), "");
+}
+
+static INLINE LLVMValueRef
+to_8_unorm(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ LLVMValueRef uscaled = LLVMBuildFPToUI(builder, l, LLVMIntType(8), "");
+ return LLVMBuildFMul(builder, uscaled,
+ LLVMConstReal(builder, 255.));
+}
+
+static INLINE LLVMValueRef
+to_16_unorm(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ LLVMValueRef uscaled = LLVMBuildFPToUI(builder, l, LLVMIntType(32), "");
+ return LLVMBuildFMul(builder, uscaled,
+ LLVMConstReal(builder, 65535.));
+}
+
+static INLINE LLVMValueRef
+to_32_unorm(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ LLVMValueRef uscaled = LLVMBuildFPToUI(builder, l, LLVMIntType(32), "");
+
+ return LLVMBuildFMul(builder, uscaled,
+ LLVMConstReal(builder, 4294967295.));
+}
+
+static INLINE LLVMValueRef
+to_8_snorm(LLVMBuilderRef builder, LLVMValueRef val)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, val, "");
+ LLVMValueRef uscaled = LLVMBuildFPToSI(builder, l, LLVMIntType(8), "");
+ return LLVMBuildFMUL(builder, uscaled,
+ LLVMConstReal(builder, 127.0));
+}
+
+static INLINE LLVMValueRef
+to_16_snorm(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ LLVMValueRef uscaled = LLVMBuildFPToSI(builder, l, LLVMIntType(16), "");
+ return LLVMBuildFMul(builder, uscaled,
+ LLVMConstReal(builder, 32767.0f));
+}
+
+static INLINE LLVMValueRef
+to_32_snorm(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ LLVMValueRef uscaled = LLVMBuildFPToSI(builder, l, LLVMIntType(32), "");
+
+ return LLVMBuildFMUL(builder, uscaled,
+ LLVMConstReal(builder, 2147483647.0));
+}
+
+static INLINE LLVMValueRef
+to_32_fixed(LLVMBuilderRef builder, LLVMValueRef fp)
+{
+ LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
+ LLVMValueRef uscaled = LLVMBuildFPToSI(builder, l, LLVMIntType(32), "");
+
+ return LLVMBuildFMul(builder, uscaled,
+ LLVMConstReal(builder, 65536.0));
+}
+
+static LLVMValueRef
+fetch(LLVMValueRef ptr, int val_size, int nr_components,
+ LLVMValueRef res)
+{
+ int i;
+ int offset = 0;
+
+ for (i = 0; i < nr_components; ++i) {
+ LLVMValueRef src_index = LLVMConstInt(LLVMInt32Type(), offset, 0);
+ LLVMValueRef dst_index = LLVMConstInt(LLVMInt32Type(), i, 0);
+ //getelementptr i8* ptr, i64 offset
+ LLVMValueRef src_tmp = LLVMBuildGEP(builder, ptr, &src_index, 1, "");
+ //getelementptr float* res, i64 i
+ LLVMValueRef res_tmp = LLVMBuildGEP(builder, res, &dst_index, 1, "");
+ //bitcast i8* src, to res_type*
+ //load res_type src
+ //convert res_type src to float
+ //store float src, float *dst src
+ offset += val_size;
+ }
+}
+
+
+static void
+fetch_B8G8R8A8_UNORM(const void *ptr, float *attrib)
+{
+ attrib[2] = FROM_8_UNORM(0);
+ attrib[1] = FROM_8_UNORM(1);
+ attrib[0] = FROM_8_UNORM(2);
+ attrib[3] = FROM_8_UNORM(3);
+}
+
+static void
+emit_B8G8R8A8_UNORM( const float *attrib, void *ptr)
+{
+ ubyte *out = (ubyte *)ptr;
+ out[2] = TO_8_UNORM(attrib[0]);
+ out[1] = TO_8_UNORM(attrib[1]);
+ out[0] = TO_8_UNORM(attrib[2]);
+ out[3] = TO_8_UNORM(attrib[3]);
+}
+
+static void
+fetch_NULL( const void *ptr, float *attrib )
+{
+ attrib[0] = 0;
+ attrib[1] = 0;
+ attrib[2] = 0;
+ attrib[3] = 1;
+}
+
+static void
+emit_NULL( const float *attrib, void *ptr )
+{
+ /* do nothing is the only sensible option */
+}
+
+typedef LLVMValueRef (*from_func)(LLVMBuilderRef, LLVMValueRef);
+typedef LLVMValueRef (*to_func)(LLVMBuilderRef, LLVMValueRef);
+
+struct draw_llvm_translate {
+ int format;
+ from_func from;
+ to_func to;
+ LLVMTypeRef type;
+ int num_components;
+} translates[] =
+{
+ {PIPE_FORMAT_R64_FLOAT, from_64_float, to_64_float, LLVMDoubleType(), 1},
+ {PIPE_FORMAT_R64G64_FLOAT, from_64_float, to_64_float, LLVMDoubleType(), 2},
+ {PIPE_FORMAT_R64G64B64_FLOAT, from_64_float, to_64_float, LLVMDoubleType(), 3},
+ {PIPE_FORMAT_R64G64B64A64_FLOAT, from_64_float, to_64_float, LLVMDoubleType(), 4},
+
+ {PIPE_FORMAT_R32_FLOAT, from_32_float, to_32_float, LLVMFloatType(), 1},
+ {PIPE_FORMAT_R32G32_FLOAT, from_32_float, to_32_float, LLVMFloatType(), 2},
+ {PIPE_FORMAT_R32G32B32_FLOAT, from_32_float, to_32_float, LLVMFloatType(), 3},
+ {PIPE_FORMAT_R32G32B32A32_FLOAT, from_32_float, to_32_float, LLVMFloatType(), 4},
+
+ {PIPE_FORMAT_R32_UNORM, from_32_unorm, to_32_unorm, LLVMIntType(32), 1},
+ {PIPE_FORMAT_R32G32_UNORM, from_32_unorm, to_32_unorm, LLVMIntType(32), 2},
+ {PIPE_FORMAT_R32G32B32_UNORM, from_32_unorm, to_32_unorm, LLVMIntType(32), 3},
+ {PIPE_FORMAT_R32G32B32A32_UNORM, from_32_unorm, to_32_unorm, LLVMIntType(32), 4},
+
+ {PIPE_FORMAT_R32_USCALED, from_32_uscaled, to_32_uscaled, LLVMIntType(32), 1},
+ {PIPE_FORMAT_R32G32_USCALED, from_32_uscaled, to_32_uscaled, LLVMIntType(32), 2},
+ {PIPE_FORMAT_R32G32B32_USCALED, from_32_uscaled, to_32_uscaled, LLVMIntType(32), 3},
+ {PIPE_FORMAT_R32G32B32A32_USCALED, from_32_uscaled, to_32_uscaled, LLVMIntType(32), 4},
+
+ {PIPE_FORMAT_R32_SNORM, from_32_snorm, to_32_snorm, LLVMIntType(32), 1},
+ {PIPE_FORMAT_R32G32_SNORM, from_32_snorm, to_32_snorm, LLVMIntType(32), 2},
+ {PIPE_FORMAT_R32G32B32_SNORM, from_32_snorm, to_32_snorm, LLVMIntType(32), 3},
+ {PIPE_FORMAT_R32G32B32A32_SNORM, from_32_snorm, to_32_snorm, LLVMIntType(32), 4},
+
+ {PIPE_FORMAT_R32_SSCALED, from_32_sscaled, to_32_sscaled, LLVMIntType(32), 1},
+ {PIPE_FORMAT_R32G32_SSCALED, from_32_sscaled, to_32_sscaled, LLVMIntType(32), 2},
+ {PIPE_FORMAT_R32G32B32_SSCALED, from_32_sscaled, to_32_sscaled, LLVMIntType(32), 3},
+ {PIPE_FORMAT_R32G32B32A32_SSCALED, from_32_sscaled, to_32_sscaled, LLVMIntType(32), 4},
+
+ {PIPE_FORMAT_R16_UNORM, from_16_unorm, to_16_unorm, LLVMIntType(16), 1},
+ {PIPE_FORMAT_R16G16_UNORM, from_16_unorm, to_16_unorm, LLVMIntType(16), 2},
+ {PIPE_FORMAT_R16G16B16_UNORM, from_16_unorm, to_16_unorm, LLVMIntType(16), 3},
+ {PIPE_FORMAT_R16G16B16A16_UNORM, from_16_unorm, to_16_unorm, LLVMIntType(16), 4},
+
+ {PIPE_FORMAT_R16_USCALED, from_16_uscaled, to_16_uscaled, LLVMIntType(16), 1},
+ {PIPE_FORMAT_R16G16_USCALED, from_16_uscaled, to_16_uscaled, LLVMIntType(16), 2},
+ {PIPE_FORMAT_R16G16B16_USCALED, from_16_uscaled, to_16_uscaled, LLVMIntType(16), 3},
+ {PIPE_FORMAT_R16G16B16A16_USCALED, from_16_uscaled, to_16_uscaled, LLVMIntType(16), 4},
+
+ {PIPE_FORMAT_R16_SNORM, from_16_snorm, to_16_snorm, LLVMIntType(16), 1},
+ {PIPE_FORMAT_R16G16_SNORM, from_16_snorm, to_16_snorm, LLVMIntType(16), 2},
+ {PIPE_FORMAT_R16G16B16_SNORM, from_16_snorm, to_16_snorm, LLVMIntType(16), 3},
+ {PIPE_FORMAT_R16G16B16A16_SNORM, from_16_snorm, to_16_snorm, LLVMIntType(16), 4},
+
+ {PIPE_FORMAT_R16_SSCALED, from_16_sscaled, to_16_sscaled, LLVMIntType(16), 1},
+ {PIPE_FORMAT_R16G16_SSCALED, from_16_sscaled, to_16_sscaled, LLVMIntType(16), 2},
+ {PIPE_FORMAT_R16G16B16_SSCALED, from_16_sscaled, to_16_sscaled, LLVMIntType(16), 3},
+ {PIPE_FORMAT_R16G16B16A16_SSCALED, from_16_sscaled, to_16_sscaled, LLVMIntType(16), 4},
+
+ {PIPE_FORMAT_R8_UNORM, from_8_unorm, to_8_unorm, LLVMIntType(8), 1},
+ {PIPE_FORMAT_R8G8_UNORM, from_8_unorm, to_8_unorm, LLVMIntType(8), 2},
+ {PIPE_FORMAT_R8G8B8_UNORM, from_8_unorm, to_8_unorm, LLVMIntType(8), 3},
+ {PIPE_FORMAT_R8G8B8A8_UNORM, from_8_unorm, to_8_unorm, LLVMIntType(8), 4},
+
+ {PIPE_FORMAT_R8_USCALED, from_8_uscaled, to_8_uscaled, LLVMIntType(8), 1},
+ {PIPE_FORMAT_R8G8_USCALED, from_8_uscaled, to_8_uscaled, LLVMIntType(8), 2},
+ {PIPE_FORMAT_R8G8B8_USCALED, from_8_uscaled, to_8_uscaled, LLVMIntType(8), 3},
+ {PIPE_FORMAT_R8G8B8A8_USCALED, from_8_uscaled, to_8_uscaled, LLVMIntType(8), 4},
+
+ {PIPE_FORMAT_R8_SNORM, from_8_snorm, to_8_snorm, LLVMIntType(8), 1},
+ {PIPE_FORMAT_R8G8_SNORM, from_8_snorm, to_8_snorm, LLVMIntType(8), 2},
+ {PIPE_FORMAT_R8G8B8_SNORM, from_8_snorm, to_8_snorm, LLVMIntType(8), 3},
+ {PIPE_FORMAT_R8G8B8A8_SNORM, from_8_snorm, to_8_snorm, LLVMIntType(8), 4},
+
+ {PIPE_FORMAT_R8_SSCALED, from_8_sscaled, to_8_sscaled, LLVMIntType(8), 1},
+ {PIPE_FORMAT_R8G8_SSCALED, from_8_sscaled, to_8_sscaled, LLVMIntType(8), 2},
+ {PIPE_FORMAT_R8G8B8_SSCALED, from_8_sscaled, to_8_sscaled, LLVMIntType(8), 3},
+ {PIPE_FORMAT_R8G8B8A8_SSCALED, from_8_sscaled, to_8_sscaled, LLVMIntType(8), 4},
+
+ {PIPE_FORMAT_R32_FIXED, from_32_fixed, to_32_fixed, LLVMIntType(32), 1},
+ {PIPE_FORMAT_R32G32_FIXED, from_32_fixed, to_32_fixed, LLVMIntType(32), 2},
+ {PIPE_FORMAT_R32G32B32_FIXED, from_32_fixed, to_32_fixed, LLVMIntType(32), 3},
+ {PIPE_FORMAT_R32G32B32A32_FIXED, from_32_fixed, to_32_fixed, LLVMIntType(32), 4},
+
+ {PIPE_FORMAT_A8R8G8B8_UNORM, from_8_unorm, to_8_unorm, LLVMIntType(8), 4},
+ {PIPE_FORMAT_B8G8R8A8_UNORM, from_8_unorm, to_8_unorm, LLVMIntType(), 4},
+};
+
+/**
+ * Fetch vertex attributes for 'count' vertices.
+ */
+static void PIPE_CDECL generic_run_elts( struct translate *translate,
+ const unsigned *elts,
+ unsigned count,
+ unsigned instance_id,
+ void *output_buffer )
+{
+ struct translate_generic *tg = translate_generic(translate);
+ char *vert = output_buffer;
+ unsigned nr_attrs = tg->nr_attrib;
+ unsigned attr;
+ unsigned i;
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (i = 0; i < count; i++) {
+ unsigned elt = *elts++;
+
+ for (attr = 0; attr < nr_attrs; attr++) {
+ float data[4];
+ const char *src;
+
+ char *dst = (vert +
+ tg->attrib[attr].output_offset);
+
+ if (tg->attrib[attr].instance_divisor) {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride *
+ (instance_id / tg->attrib[attr].instance_divisor);
+ } else {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride * elt;
+ }
+
+ tg->attrib[attr].fetch( src, data );
+
+ if (0) debug_printf("vert %d/%d attr %d: %f %f %f %f\n",
+ i, elt, attr, data[0], data[1], data[2], data[3]);
+
+ tg->attrib[attr].emit( data, dst );
+ }
+
+ vert += tg->translate.key.output_stride;
+ }
+}
+
+
+
+static void PIPE_CDECL generic_run( struct translate *translate,
+ unsigned start,
+ unsigned count,
+ unsigned instance_id,
+ void *output_buffer )
+{
+ struct translate_generic *tg = translate_generic(translate);
+ char *vert = output_buffer;
+ unsigned nr_attrs = tg->nr_attrib;
+ unsigned attr;
+ unsigned i;
+
+ /* loop over vertex attributes (vertex shader inputs)
+ */
+ for (i = 0; i < count; i++) {
+ unsigned elt = start + i;
+
+ for (attr = 0; attr < nr_attrs; attr++) {
+ float data[4];
+
+ char *dst = (vert +
+ tg->attrib[attr].output_offset);
+
+ if (tg->attrib[attr].type == TRANSLATE_ELEMENT_NORMAL) {
+ const char *src;
+
+ if (tg->attrib[attr].instance_divisor) {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride *
+ (instance_id / tg->attrib[attr].instance_divisor);
+ } else {
+ src = tg->attrib[attr].input_ptr +
+ tg->attrib[attr].input_stride * elt;
+ }
+
+ tg->attrib[attr].fetch( src, data );
+ } else {
+ data[0] = (float)instance_id;
+ }
+
+ if (0) debug_printf("vert %d attr %d: %f %f %f %f\n",
+ i, attr, data[0], data[1], data[2], data[3]);
+
+ tg->attrib[attr].emit( data, dst );
+ }
+
+ vert += tg->translate.key.output_stride;
+ }
+}
+
+
+
+static void generic_set_buffer( struct translate *translate,
+ unsigned buf,
+ const void *ptr,
+ unsigned stride )
+{
+ struct translate_generic *tg = translate_generic(translate);
+ unsigned i;
+
+ for (i = 0; i < tg->nr_attrib; i++) {
+ if (tg->attrib[i].buffer == buf) {
+ tg->attrib[i].input_ptr = ((char *)ptr +
+ tg->attrib[i].input_offset);
+ tg->attrib[i].input_stride = stride;
+ }
+ }
+}
+
+
+static void generic_release( struct translate *translate )
+{
+ /* Refcount?
+ */
+ FREE(translate);
+}
+
+struct translate *translate_generic_create( const struct translate_key *key )
+{
+ struct translate_generic *tg = CALLOC_STRUCT(translate_generic);
+ unsigned i;
+
+ if (tg == NULL)
+ return NULL;
+
+ tg->translate.key = *key;
+ tg->translate.release = generic_release;
+ tg->translate.set_buffer = generic_set_buffer;
+ tg->translate.run_elts = generic_run_elts;
+ tg->translate.run = generic_run;
+
+ for (i = 0; i < key->nr_elements; i++) {
+ tg->attrib[i].type = key->element[i].type;
+
+ tg->attrib[i].fetch = get_fetch_func(key->element[i].input_format);
+ tg->attrib[i].buffer = key->element[i].input_buffer;
+ tg->attrib[i].input_offset = key->element[i].input_offset;
+ tg->attrib[i].instance_divisor = key->element[i].instance_divisor;
+
+ tg->attrib[i].emit = get_emit_func(key->element[i].output_format);
+ tg->attrib[i].output_offset = key->element[i].output_offset;
+
+ }
+
+ tg->nr_attrib = key->nr_elements;
+
+
+ return &tg->translate;
+}