r300g: fix texturing with negative lod bias
[mesa.git] / src / gallium / drivers / llvmpipe / lp_setup_tri.c
index f8a581657335d525bc0da81be4ceceff06e62c65..4e2e17f77b1eb03b4a4a43c444f07fc8badb46bb 100644 (file)
@@ -34,6 +34,7 @@
 #include "lp_perf.h"
 #include "lp_setup_context.h"
 #include "lp_rast.h"
+#include "lp_state_fs.h"
 
 #define NUM_CHANNELS 4
 
@@ -146,20 +147,32 @@ setup_fragcoord_coef(struct lp_setup_context *setup,
                      unsigned slot,
                      const float (*v1)[4],
                      const float (*v2)[4],
-                     const float (*v3)[4])
+                     const float (*v3)[4],
+                     unsigned usage_mask)
 {
    /*X*/
-   tri->inputs.a0[slot][0] = 0.0;
-   tri->inputs.dadx[slot][0] = 1.0;
-   tri->inputs.dady[slot][0] = 0.0;
+   if (usage_mask & TGSI_WRITEMASK_X) {
+      tri->inputs.a0[slot][0] = 0.0;
+      tri->inputs.dadx[slot][0] = 1.0;
+      tri->inputs.dady[slot][0] = 0.0;
+   }
+
    /*Y*/
-   tri->inputs.a0[slot][1] = 0.0;
-   tri->inputs.dadx[slot][1] = 0.0;
-   tri->inputs.dady[slot][1] = 1.0;
+   if (usage_mask & TGSI_WRITEMASK_Y) {
+      tri->inputs.a0[slot][1] = 0.0;
+      tri->inputs.dadx[slot][1] = 0.0;
+      tri->inputs.dady[slot][1] = 1.0;
+   }
+
    /*Z*/
-   linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 2);
+   if (usage_mask & TGSI_WRITEMASK_Z) {
+      linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 2);
+   }
+
    /*W*/
-   linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 3);
+   if (usage_mask & TGSI_WRITEMASK_W) {
+      linear_coef(setup, tri, oneoverarea, slot, v1, v2, v3, 0, 3);
+   }
 }
 
 
@@ -170,13 +183,21 @@ setup_fragcoord_coef(struct lp_setup_context *setup,
 static void setup_facing_coef( struct lp_setup_context *setup,
                                struct lp_rast_triangle *tri,
                                unsigned slot,
-                               boolean frontface )
+                               boolean frontface,
+                               unsigned usage_mask)
 {
    /* convert TRUE to 1.0 and FALSE to -1.0 */
-   constant_coef( setup, tri, slot, 2.0f * frontface - 1.0f, 0 );
-   constant_coef( setup, tri, slot, 0.0f, 1 ); /* wasted */
-   constant_coef( setup, tri, slot, 0.0f, 2 ); /* wasted */
-   constant_coef( setup, tri, slot, 0.0f, 3 ); /* wasted */
+   if (usage_mask & TGSI_WRITEMASK_X)
+      constant_coef( setup, tri, slot, 2.0f * frontface - 1.0f, 0 );
+
+   if (usage_mask & TGSI_WRITEMASK_Y)
+      constant_coef( setup, tri, slot, 0.0f, 1 ); /* wasted */
+
+   if (usage_mask & TGSI_WRITEMASK_Z)
+      constant_coef( setup, tri, slot, 0.0f, 2 ); /* wasted */
+
+   if (usage_mask & TGSI_WRITEMASK_W)
+      constant_coef( setup, tri, slot, 0.0f, 3 ); /* wasted */
 }
 
 
@@ -191,48 +212,65 @@ static void setup_tri_coefficients( struct lp_setup_context *setup,
                                    const float (*v3)[4],
                                    boolean frontface)
 {
+   unsigned fragcoord_usage_mask = TGSI_WRITEMASK_XYZ;
    unsigned slot;
 
-   /* The internal position input is in slot zero:
-    */
-   setup_fragcoord_coef(setup, tri, oneoverarea, 0, v1, v2, v3);
-
    /* setup interpolation for all the remaining attributes:
     */
    for (slot = 0; slot < setup->fs.nr_inputs; slot++) {
       unsigned vert_attr = setup->fs.input[slot].src_index;
+      unsigned usage_mask = setup->fs.input[slot].usage_mask;
       unsigned i;
 
       switch (setup->fs.input[slot].interp) {
       case LP_INTERP_CONSTANT:
-         for (i = 0; i < NUM_CHANNELS; i++)
-            constant_coef(setup, tri, slot+1, v3[vert_attr][i], i);
+         if (setup->flatshade_first) {
+            for (i = 0; i < NUM_CHANNELS; i++)
+               if (usage_mask & (1 << i))
+                  constant_coef(setup, tri, slot+1, v1[vert_attr][i], i);
+         }
+         else {
+            for (i = 0; i < NUM_CHANNELS; i++)
+               if (usage_mask & (1 << i))
+                  constant_coef(setup, tri, slot+1, v3[vert_attr][i], i);
+         }
          break;
 
       case LP_INTERP_LINEAR:
          for (i = 0; i < NUM_CHANNELS; i++)
-            linear_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
+            if (usage_mask & (1 << i))
+               linear_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
          break;
 
       case LP_INTERP_PERSPECTIVE:
          for (i = 0; i < NUM_CHANNELS; i++)
-            perspective_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
+            if (usage_mask & (1 << i))
+               perspective_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3, vert_attr, i);
+         fragcoord_usage_mask |= TGSI_WRITEMASK_W;
          break;
 
       case LP_INTERP_POSITION:
-         /* XXX: fix me - duplicates the values in slot zero.
+         /*
+          * The generated pixel interpolators will pick up the coeffs from
+          * slot 0, so all need to ensure that the usage mask is covers all
+          * usages.
           */
-         setup_fragcoord_coef(setup, tri, oneoverarea, slot+1, v1, v2, v3);
+         fragcoord_usage_mask |= usage_mask;
          break;
 
       case LP_INTERP_FACING:
-         setup_facing_coef(setup, tri, slot+1, frontface);
+         setup_facing_coef(setup, tri, slot+1, frontface, usage_mask);
          break;
 
       default:
          assert(0);
       }
    }
+
+   /* The internal position input is in slot zero:
+    */
+   setup_fragcoord_coef(setup, tri, oneoverarea, 0, v1, v2, v3,
+                        fragcoord_usage_mask);
 }
 
 
@@ -266,12 +304,14 @@ alloc_triangle(struct lp_scene *scene, unsigned nr_inputs, unsigned *tri_size)
 
    tri = lp_scene_alloc_aligned( scene, bytes, 16 );
 
-   inputs = (char *) (tri + 1);
-   tri->inputs.a0   = (float (*)[4]) inputs;
-   tri->inputs.dadx = (float (*)[4]) (inputs + input_array_sz);
-   tri->inputs.dady = (float (*)[4]) (inputs + 2 * input_array_sz);
+   if (tri) {
+      inputs = (char *) (tri + 1);
+      tri->inputs.a0   = (float (*)[4]) inputs;
+      tri->inputs.dadx = (float (*)[4]) (inputs + input_array_sz);
+      tri->inputs.dady = (float (*)[4]) (inputs + 2 * input_array_sz);
 
-   *tri_size = bytes;
+      *tri_size = bytes;
+   }
 
    return tri;
 }
@@ -335,6 +375,8 @@ do_triangle_ccw(struct lp_setup_context *setup,
       print_triangle(setup, v1, v2, v3);
 
    tri = alloc_triangle(scene, setup->fs.nr_inputs, &tri_bytes);
+   if (!tri)
+      return;
 
 #ifdef DEBUG
    tri->v[0][0] = v1[0][0];
@@ -569,7 +611,8 @@ do_triangle_ccw(struct lp_setup_context *setup,
                /* triangle covers the whole tile- shade whole tile */
                LP_COUNT(nr_fully_covered_64);
               in = TRUE;
-              if(setup->fs.current.opaque) {
+              if (setup->fs.current.variant->opaque &&
+                  !setup->fb.zsbuf) {
                  lp_scene_bin_reset( scene, x, y );
                  lp_scene_bin_command( scene, x, y,
                                        lp_rast_set_state,
@@ -665,14 +708,14 @@ void
 lp_setup_choose_triangle( struct lp_setup_context *setup )
 {
    switch (setup->cullmode) {
-   case PIPE_WINDING_NONE:
+   case PIPE_FACE_NONE:
       setup->triangle = triangle_both;
       break;
-   case PIPE_WINDING_CCW:
-      setup->triangle = triangle_cw;
+   case PIPE_FACE_BACK:
+      setup->triangle = setup->ccw_is_frontface ? triangle_ccw : triangle_cw;
       break;
-   case PIPE_WINDING_CW:
-      setup->triangle = triangle_ccw;
+   case PIPE_FACE_FRONT:
+      setup->triangle = setup->ccw_is_frontface ? triangle_cw : triangle_ccw;
       break;
    default:
       setup->triangle = triangle_nop;