gallium: a lot more complete implementation of stream output
[mesa.git] / src / gallium / auxiliary / draw / draw_llvm_translate.c
index 012ca3f6f03d997e949e9b06385a27b1ea5d87df..d7da7ed357d0ef47e7e3f66e07d65b8a4d63983b 100644 (file)
@@ -1,99 +1,34 @@
+#include "draw_private.h"
+#include "draw_context.h"
 
+#include "draw_llvm.h"
 
+#include "gallivm/lp_bld_arit.h"
+#include "gallivm/lp_bld_struct.h"
+#include "gallivm/lp_bld_format.h"
+#include "gallivm/lp_bld_debug.h"
 
 #include "util/u_memory.h"
+#include "util/u_format.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
+static  LLVMValueRef
 from_64_float(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMDoubleType() , "");
+                                      LLVMPointerType(LLVMDoubleType(), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    return LLVMBuildFPTrunc(builder, l, LLVMFloatType(), "");
 }
 
-static INLINE LLVMValueRef
+static LLVMValueRef
 from_32_float(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMFloatType() , "");
+                                      LLVMPointerType(LLVMFloatType(), 0) , "");
    return LLVMBuildLoad(builder, bc, "");
 }
 
@@ -108,7 +43,7 @@ static INLINE LLVMValueRef
 from_16_uscaled(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(16) , "");
+                                      LLVMPointerType(LLVMIntType(16), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    return LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
 }
@@ -117,7 +52,7 @@ static INLINE LLVMValueRef
 from_32_uscaled(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(32) , "");
+                                      LLVMPointerType(LLVMIntType(32), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    return LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
 }
@@ -133,7 +68,7 @@ static INLINE LLVMValueRef
 from_16_sscaled(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(16) , "");
+                                      LLVMPointerType(LLVMIntType(16), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    return LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
 }
@@ -142,7 +77,7 @@ static INLINE LLVMValueRef
 from_32_sscaled(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(32) , "");
+                                      LLVMPointerType(LLVMIntType(32), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    return LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
 }
@@ -154,30 +89,30 @@ 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.));
+                        LLVMConstReal(LLVMFloatType(), 255.), "");
 }
 
 static INLINE LLVMValueRef
 from_16_unorm(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(16) , "");
+                                      LLVMPointerType(LLVMIntType(16), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    LLVMValueRef uscaled = LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
    return LLVMBuildFDiv(builder, uscaled,
-                        LLVMConstReal(builder, 65535.));
+                        LLVMConstReal(LLVMFloatType(), 65535.), "");
 }
 
 static INLINE LLVMValueRef
 from_32_unorm(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(32) , "");
+                                      LLVMPointerType(LLVMIntType(32), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    LLVMValueRef uscaled = LLVMBuildUIToFP(builder, l, LLVMFloatType(), "");
 
    return LLVMBuildFDiv(builder, uscaled,
-                        LLVMConstReal(builder, 4294967295.));
+                        LLVMConstReal(LLVMFloatType(), 4294967295.), "");
 }
 
 static INLINE LLVMValueRef
@@ -186,58 +121,58 @@ 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));
+                        LLVMConstReal(LLVMFloatType(), 127.0), "");
 }
 
 static INLINE LLVMValueRef
 from_16_snorm(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(16) , "");
+                                      LLVMPointerType(LLVMIntType(16), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    LLVMValueRef uscaled = LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
    return LLVMBuildFDiv(builder, uscaled,
-                        LLVMConstReal(builder, 32767.0f));
+                        LLVMConstReal(LLVMFloatType(), 32767.0f), "");
 }
 
 static INLINE LLVMValueRef
 from_32_snorm(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(32) , "");
+                                      LLVMPointerType(LLVMIntType(32), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    LLVMValueRef uscaled = LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
 
    return LLVMBuildFDiv(builder, uscaled,
-                        LLVMConstReal(builder, 2147483647.0));
+                        LLVMConstReal(LLVMFloatType(), 2147483647.0), "");
 }
 
 static INLINE LLVMValueRef
 from_32_fixed(LLVMBuilderRef builder, LLVMValueRef val)
 {
    LLVMValueRef bc = LLVMBuildBitCast(builder, val,
-                                      LLVMIntType(32) , "");
+                                      LLVMPointerType(LLVMIntType(32), 0) , "");
    LLVMValueRef l = LLVMBuildLoad(builder, bc, "");
    LLVMValueRef uscaled = LLVMBuildSIToFP(builder, l, LLVMFloatType(), "");
 
    return LLVMBuildFDiv(builder, uscaled,
-                        LLVMConstReal(builder, 65536.0));
+                        LLVMConstReal(LLVMFloatType(), 65536.0), "");
 }
 
-static INLINE LLVMValueRef
+static LLVMValueRef
 to_64_float(LLVMBuilderRef builder, LLVMValueRef fp)
 {
    LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
    return LLVMBuildFPExt(builder, l, LLVMDoubleType(), "");
 }
 
-static INLINE LLVMValueRef
+static LLVMValueRef
 to_32_float(LLVMBuilderRef builder, LLVMValueRef fp)
 {
    return LLVMBuildLoad(builder, fp, "");
 }
 
-atic INLINE LLVMValueRef
+static INLINE LLVMValueRef
 to_8_uscaled(LLVMBuilderRef builder, LLVMValueRef fp)
 {
    LLVMValueRef l = LLVMBuildLoad(builder, fp, "");
@@ -285,7 +220,7 @@ 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.));
+                        LLVMConstReal(LLVMFloatType(), 255.), "");
 }
 
 static INLINE LLVMValueRef
@@ -294,7 +229,7 @@ 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.));
+                        LLVMConstReal(LLVMFloatType(), 65535.), "");
 }
 
 static INLINE LLVMValueRef
@@ -304,7 +239,7 @@ to_32_unorm(LLVMBuilderRef builder, LLVMValueRef fp)
    LLVMValueRef uscaled = LLVMBuildFPToUI(builder, l, LLVMIntType(32), "");
 
    return LLVMBuildFMul(builder, uscaled,
-                        LLVMConstReal(builder, 4294967295.));
+                        LLVMConstReal(LLVMFloatType(), 4294967295.), "");
 }
 
 static INLINE LLVMValueRef
@@ -312,8 +247,8 @@ 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));
+   return LLVMBuildFMul(builder, uscaled,
+                        LLVMConstReal(LLVMFloatType(), 127.0), "");
 }
 
 static INLINE LLVMValueRef
@@ -322,7 +257,7 @@ 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));
+                        LLVMConstReal(LLVMFloatType(), 32767.0f), "");
 }
 
 static INLINE LLVMValueRef
@@ -331,8 +266,8 @@ 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));
+   return LLVMBuildFMul(builder, uscaled,
+                        LLVMConstReal(LLVMFloatType(), 2147483647.0), "");
 }
 
 static INLINE LLVMValueRef
@@ -342,167 +277,221 @@ to_32_fixed(LLVMBuilderRef builder, LLVMValueRef 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);
+                        LLVMConstReal(LLVMFloatType(), 65536.0), "");
 }
 
-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]);
-}
+typedef LLVMValueRef (*from_func)(LLVMBuilderRef, LLVMValueRef);
+typedef  LLVMValueRef (*to_func)(LLVMBuilderRef, LLVMValueRef);
 
-static void
-fetch_NULL( const void *ptr, float *attrib )
-{
-   attrib[0] = 0;
-   attrib[1] = 0;
-   attrib[2] = 0;
-   attrib[3] = 1;
-}
+/* so that underneath can avoid function calls which are prohibited
+ * for static initialization we need this conversion */
+enum ll_type {
+   LL_Double,
+   LL_Float,
+   LL_Int32,
+   LL_Int16,
+   LL_Int8
+};
 
-static void
-emit_NULL( const float *attrib, void *ptr )
-{
-   /* do nothing is the only sensible option */
+static INLINE LLVMTypeRef
+ll_type_to_llvm(enum ll_type type)
+{
+   switch (type) {
+   case LL_Double:
+      return LLVMDoubleType();
+   case LL_Float:
+      return LLVMFloatType();
+   case LL_Int32:
+      return LLVMInt32Type();
+   case LL_Int16:
+      return LLVMIntType(16);
+   case LL_Int8:
+      return LLVMIntType(8);
+   }
+   return LLVMIntType(8);
+}
+
+static INLINE int
+ll_type_size(enum ll_type type)
+{
+   switch (type) {
+   case LL_Double:
+      return 8;
+   case LL_Float:
+      return 4;
+   case LL_Int32:
+      return 4;
+   case LL_Int16:
+      return 2;
+   case LL_Int8:
+      return 1;
+   }
+   return 1;
 }
 
-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;
+   enum ll_type 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},
+   {PIPE_FORMAT_R64_FLOAT,          from_64_float, to_64_float, LL_Double, 1},
+   {PIPE_FORMAT_R64G64_FLOAT,       from_64_float, to_64_float, LL_Double, 2},
+   {PIPE_FORMAT_R64G64B64_FLOAT,    from_64_float, to_64_float, LL_Double, 3},
+   {PIPE_FORMAT_R64G64B64A64_FLOAT, from_64_float, to_64_float, LL_Double, 4},
+   {PIPE_FORMAT_R32_FLOAT,          from_32_float, to_32_float, LL_Float, 1},
+   {PIPE_FORMAT_R32G32_FLOAT,       from_32_float, to_32_float, LL_Float, 2},
+   {PIPE_FORMAT_R32G32B32_FLOAT,    from_32_float, to_32_float, LL_Float, 3},
+   {PIPE_FORMAT_R32G32B32A32_FLOAT, from_32_float, to_32_float, LL_Float, 4},
+
+   {PIPE_FORMAT_R32_UNORM,          from_32_unorm, to_32_unorm, LL_Int32, 1},
+   {PIPE_FORMAT_R32G32_UNORM,       from_32_unorm, to_32_unorm, LL_Int32, 2},
+   {PIPE_FORMAT_R32G32B32_UNORM,    from_32_unorm, to_32_unorm, LL_Int32, 3},
+   {PIPE_FORMAT_R32G32B32A32_UNORM, from_32_unorm, to_32_unorm, LL_Int32, 4},
+
+   {PIPE_FORMAT_R32_USCALED,          from_32_uscaled, to_32_uscaled, LL_Int32, 1},
+   {PIPE_FORMAT_R32G32_USCALED,       from_32_uscaled, to_32_uscaled, LL_Int32, 2},
+   {PIPE_FORMAT_R32G32B32_USCALED,    from_32_uscaled, to_32_uscaled, LL_Int32, 3},
+   {PIPE_FORMAT_R32G32B32A32_USCALED, from_32_uscaled, to_32_uscaled, LL_Int32, 4},
+
+   {PIPE_FORMAT_R32_SNORM,          from_32_snorm, to_32_snorm, LL_Int32, 1},
+   {PIPE_FORMAT_R32G32_SNORM,       from_32_snorm, to_32_snorm, LL_Int32, 2},
+   {PIPE_FORMAT_R32G32B32_SNORM,    from_32_snorm, to_32_snorm, LL_Int32, 3},
+   {PIPE_FORMAT_R32G32B32A32_SNORM, from_32_snorm, to_32_snorm, LL_Int32, 4},
+
+   {PIPE_FORMAT_R32_SSCALED,          from_32_sscaled, to_32_sscaled, LL_Int32, 1},
+   {PIPE_FORMAT_R32G32_SSCALED,       from_32_sscaled, to_32_sscaled, LL_Int32, 2},
+   {PIPE_FORMAT_R32G32B32_SSCALED,    from_32_sscaled, to_32_sscaled, LL_Int32, 3},
+   {PIPE_FORMAT_R32G32B32A32_SSCALED, from_32_sscaled, to_32_sscaled, LL_Int32, 4},
+
+   {PIPE_FORMAT_R16_UNORM,          from_16_unorm, to_16_unorm, LL_Int16, 1},
+   {PIPE_FORMAT_R16G16_UNORM,       from_16_unorm, to_16_unorm, LL_Int16, 2},
+   {PIPE_FORMAT_R16G16B16_UNORM,    from_16_unorm, to_16_unorm, LL_Int16, 3},
+   {PIPE_FORMAT_R16G16B16A16_UNORM, from_16_unorm, to_16_unorm, LL_Int16, 4},
+
+   {PIPE_FORMAT_R16_USCALED,          from_16_uscaled, to_16_uscaled, LL_Int16, 1},
+   {PIPE_FORMAT_R16G16_USCALED,       from_16_uscaled, to_16_uscaled, LL_Int16, 2},
+   {PIPE_FORMAT_R16G16B16_USCALED,    from_16_uscaled, to_16_uscaled, LL_Int16, 3},
+   {PIPE_FORMAT_R16G16B16A16_USCALED, from_16_uscaled, to_16_uscaled, LL_Int16, 4},
+
+   {PIPE_FORMAT_R16_SNORM,          from_16_snorm, to_16_snorm, LL_Int16, 1},
+   {PIPE_FORMAT_R16G16_SNORM,       from_16_snorm, to_16_snorm, LL_Int16, 2},
+   {PIPE_FORMAT_R16G16B16_SNORM,    from_16_snorm, to_16_snorm, LL_Int16, 3},
+   {PIPE_FORMAT_R16G16B16A16_SNORM, from_16_snorm, to_16_snorm, LL_Int16, 4},
+
+   {PIPE_FORMAT_R16_SSCALED,          from_16_sscaled, to_16_sscaled, LL_Int16, 1},
+   {PIPE_FORMAT_R16G16_SSCALED,       from_16_sscaled, to_16_sscaled, LL_Int16, 2},
+   {PIPE_FORMAT_R16G16B16_SSCALED,    from_16_sscaled, to_16_sscaled, LL_Int16, 3},
+   {PIPE_FORMAT_R16G16B16A16_SSCALED, from_16_sscaled, to_16_sscaled, LL_Int16, 4},
+
+   {PIPE_FORMAT_R8_UNORM,       from_8_unorm, to_8_unorm, LL_Int8, 1},
+   {PIPE_FORMAT_R8G8_UNORM,     from_8_unorm, to_8_unorm, LL_Int8, 2},
+   {PIPE_FORMAT_R8G8B8_UNORM,   from_8_unorm, to_8_unorm, LL_Int8, 3},
+   {PIPE_FORMAT_R8G8B8A8_UNORM, from_8_unorm, to_8_unorm, LL_Int8, 4},
+
+   {PIPE_FORMAT_R8_USCALED,       from_8_uscaled, to_8_uscaled, LL_Int8, 1},
+   {PIPE_FORMAT_R8G8_USCALED,     from_8_uscaled, to_8_uscaled, LL_Int8, 2},
+   {PIPE_FORMAT_R8G8B8_USCALED,   from_8_uscaled, to_8_uscaled, LL_Int8, 3},
+   {PIPE_FORMAT_R8G8B8A8_USCALED, from_8_uscaled, to_8_uscaled, LL_Int8, 4},
+
+   {PIPE_FORMAT_R8_SNORM,       from_8_snorm, to_8_snorm, LL_Int8, 1},
+   {PIPE_FORMAT_R8G8_SNORM,     from_8_snorm, to_8_snorm, LL_Int8, 2},
+   {PIPE_FORMAT_R8G8B8_SNORM,   from_8_snorm, to_8_snorm, LL_Int8, 3},
+   {PIPE_FORMAT_R8G8B8A8_SNORM, from_8_snorm, to_8_snorm, LL_Int8, 4},
+
+   {PIPE_FORMAT_R8_SSCALED,       from_8_sscaled, to_8_sscaled, LL_Int8, 1},
+   {PIPE_FORMAT_R8G8_SSCALED,     from_8_sscaled, to_8_sscaled, LL_Int8, 2},
+   {PIPE_FORMAT_R8G8B8_SSCALED,   from_8_sscaled, to_8_sscaled, LL_Int8, 3},
+   {PIPE_FORMAT_R8G8B8A8_SSCALED, from_8_sscaled, to_8_sscaled, LL_Int8, 4},
+
+   {PIPE_FORMAT_R32_FIXED,          from_32_fixed, to_32_fixed, LL_Int32, 1},
+   {PIPE_FORMAT_R32G32_FIXED,       from_32_fixed, to_32_fixed, LL_Int32, 2},
+   {PIPE_FORMAT_R32G32B32_FIXED,    from_32_fixed, to_32_fixed, LL_Int32, 3},
+   {PIPE_FORMAT_R32G32B32A32_FIXED, from_32_fixed, to_32_fixed, LL_Int32, 4},
 };
 
 
+static LLVMValueRef
+fetch(LLVMBuilderRef builder,
+      LLVMValueRef ptr, int val_size, int nr_components,
+      from_func func)
+{
+   int i;
+   int offset = 0;
+   LLVMValueRef res = LLVMConstNull(
+      LLVMVectorType(LLVMFloatType(), 4));
+   LLVMValueRef defaults[4];
+
+   defaults[0] = LLVMConstReal(LLVMFloatType(), 0);
+   defaults[1] = LLVMConstReal(LLVMFloatType(), 0);
+   defaults[2] = LLVMConstReal(LLVMFloatType(), 0);
+   defaults[3] = LLVMConstReal(LLVMFloatType(), 1);
+
+   for (i = 0; i < nr_components; ++i) {
+      LLVMValueRef src_index = LLVMConstInt(LLVMInt32Type(), offset, 0);
+      LLVMValueRef dst_index = LLVMConstInt(LLVMInt32Type(), i, 0);
+      LLVMValueRef src_tmp;
+      LLVMValueRef component;
+
+      src_tmp = LLVMBuildGEP(builder, ptr, &src_index, 1, "src_tmp");
+
+      /* convert src_tmp to float */
+      component = func(builder, src_tmp);
+
+      /* vec.comp = component */
+      res = LLVMBuildInsertElement(builder,
+                                   res,
+                                   component,
+                                   dst_index, "");
+      offset += val_size;
+   }
+   for (; i < 4; ++i) {
+      LLVMValueRef dst_index = LLVMConstInt(LLVMInt32Type(), i, 0);
+      res = LLVMBuildInsertElement(builder,
+                                   res,
+                                   defaults[i],
+                                   dst_index, "");
+   }
+   return res;
+}
+
+
 LLVMValueRef
 draw_llvm_translate_from(LLVMBuilderRef builder,
                          LLVMValueRef vbuffer,
                          enum pipe_format from_format)
 {
+   const struct util_format_description *format_desc;
+   LLVMValueRef zero;
    int i;
+
+   /*
+    * The above can only cope with straight arrays: no bitfields,
+    * swizzles, or half floats.
+    */
+
    for (i = 0; i < Elements(translates); ++i) {
       if (translates[i].format == from_format) {
-         return translates.from_func(builder, vbuffer, from_format);
+         /*LLVMTypeRef type = ll_type_to_llvm(translates[i].type);*/
+         return fetch(builder,
+                      vbuffer,
+                      ll_type_size(translates[i].type),
+                      translates[i].num_components,
+                      translates[i].from);
       }
    }
-   return LLVMGetUndef(LLVMTypeOf(vbuffer));
+
+
+   /*
+    * This doesn't handle anything bigger than 32bits, or half floats
+    * yet.
+    *
+    * TODO: unify all this code into lp_build_fetch_rgba_aos().
+    */
+
+   format_desc = util_format_description(from_format);
+   zero = LLVMConstNull(LLVMInt32Type());
+   return lp_build_fetch_rgba_aos(builder, format_desc, vbuffer, zero, zero);
 }