llvmpipe: handle NULL color buffer pointers
[mesa.git] / src / gallium / drivers / llvmpipe / lp_state_setup.c
index a9d17536bbf324631ded9a3421ee1632a428a916..1d79a4ab5282d4028b757d196dd0487adfca2b51 100644 (file)
@@ -50,7 +50,6 @@
 #include "lp_state_setup.h"
 
 
-
 /* currently organized to interpolate full float[4] attributes even
  * when some elements are unused.  Later, can pack vertex data more
  * closely.
@@ -131,20 +130,22 @@ emit_facing_coef(struct gallivm_state *gallivm,
    LLVMTypeRef float_type = LLVMFloatTypeInContext(gallivm->context);
    LLVMValueRef a0_0 = args->facing;
    LLVMValueRef a0_0f = LLVMBuildSIToFP(builder, a0_0, float_type, "");
+   LLVMValueRef a0, face_val;
    const unsigned char swizzles[4] = { PIPE_SWIZZLE_RED, PIPE_SWIZZLE_ZERO,
                                        PIPE_SWIZZLE_ZERO, PIPE_SWIZZLE_ZERO };
    /* Our face val is either 1 or 0 so we do
     * face = (val * 2) - 1
     * to make it 1 or -1
     */
-   LLVMValueRef face_val =
+   face_val =
       LLVMBuildFAdd(builder,
                     LLVMBuildFMul(builder, a0_0f,
                                   lp_build_const_float(gallivm, 2.0),
                                   ""),
                     lp_build_const_float(gallivm, -1.0),
                     "facing");
-   LLVMValueRef a0 = lp_build_swizzle_aos(&args->bld, face_val, swizzles);
+   face_val = lp_build_broadcast_scalar(&args->bld, face_val);
+   a0 = lp_build_swizzle_aos(&args->bld, face_val, swizzles);
 
    store_coef(gallivm, args, slot, a0, args->bld.zero, args->bld.zero);
 }
@@ -374,6 +375,19 @@ load_attribute(struct gallivm_state *gallivm,
    }
 }
 
+/*
+ * FIXME: interpolation is always done wrt fb origin (0/0).
+ * However, if some (small) tri is far away from the origin and gradients
+ * are large, this can lead to HUGE errors, since the a0 value calculated
+ * here can get very large (with the actual values inside the triangle way
+ * smaller), leading to complete loss of accuracy. This could be prevented
+ * by using some point inside (or at corner) of the tri as interpolation
+ * origin, or just use barycentric interpolation (which GL suggests and is
+ * what real hw does - you can get the barycentric coordinates from the
+ * edge functions in rasterization in principle (though we skip these
+ * sometimes completely in case of tris covering a block fully,
+ * which obviously wouldn't work)).
+ */
 static void 
 emit_coef4( struct gallivm_state *gallivm,
             struct lp_setup_args *args,
@@ -383,6 +397,7 @@ emit_coef4( struct gallivm_state *gallivm,
             LLVMValueRef a2)
 {
    LLVMBuilderRef b = gallivm->builder;
+   LLVMValueRef attr_0;
    LLVMValueRef dy20_ooa = args->dy20_ooa;
    LLVMValueRef dy01_ooa = args->dy01_ooa;
    LLVMValueRef dx20_ooa = args->dx20_ooa;
@@ -406,10 +421,10 @@ emit_coef4( struct gallivm_state *gallivm,
 
    /* Calculate a0 - the attribute value at the origin
     */
-   LLVMValueRef dadx_x0       = LLVMBuildFMul(b, dadx, x0_center, "dadx_x0");
-   LLVMValueRef dady_y0       = LLVMBuildFMul(b, dady, y0_center, "dady_y0"); 
-   LLVMValueRef attr_v0       = LLVMBuildFAdd(b, dadx_x0, dady_y0, "attr_v0");
-   LLVMValueRef attr_0        = LLVMBuildFSub(b, a0, attr_v0, "attr_0");
+   LLVMValueRef dadx_x0    = LLVMBuildFMul(b, dadx, x0_center, "dadx_x0");
+   LLVMValueRef dady_y0    = LLVMBuildFMul(b, dady, y0_center, "dady_y0");
+   LLVMValueRef attr_v0    = LLVMBuildFAdd(b, dadx_x0, dady_y0, "attr_v0");
+   attr_0                  = LLVMBuildFSub(b, a0, attr_v0, "attr_0");
 
    store_coef(gallivm, args, slot, attr_0, dadx, dady);
 }
@@ -621,7 +636,7 @@ init_args(struct gallivm_state *gallivm,
    LLVMValueRef zeroi = lp_build_const_int32(gallivm, 0);
    LLVMValueRef pixel_center, xy0_center, dxy01, dxy20, dyx20;
    LLVMValueRef e, f, ef, ooa;
-   LLVMValueRef shuffles[4];
+   LLVMValueRef shuffles[4], shuf10;
    LLVMValueRef attr_pos[3];
    struct lp_type typef4 = lp_type_float_vec(32, 128);
    struct lp_build_context bld;
@@ -649,8 +664,9 @@ init_args(struct gallivm_state *gallivm,
    shuffles[1] = zeroi;
    shuffles[2] = LLVMGetUndef(shuf_type);
    shuffles[3] = LLVMGetUndef(shuf_type);
+   shuf10 = LLVMConstVector(shuffles, 4);
 
-   dyx20 = LLVMBuildShuffleVector(b, dxy20, dxy20, LLVMConstVector(shuffles, 4), "");
+   dyx20 = LLVMBuildShuffleVector(b, dxy20, dxy20, shuf10, "");
 
    ef = LLVMBuildFMul(b, dxy01, dyx20, "ef");
    e = LLVMBuildExtractElement(b, ef, zeroi, "");