softpipe: expand quad pipeline to process >1 quad at a time
authorKeith Whitwell <keithw@vmware.com>
Fri, 24 Jul 2009 15:49:35 +0000 (16:49 +0100)
committerKeith Whitwell <keithw@vmware.com>
Fri, 24 Jul 2009 15:49:35 +0000 (16:49 +0100)
This is part one -- we still only pass a single quad down, but
the code can now cope with more.  The quads must all be from the same
tile.

14 files changed:
src/gallium/drivers/softpipe/sp_quad_alpha_test.c
src/gallium/drivers/softpipe/sp_quad_blend.c
src/gallium/drivers/softpipe/sp_quad_colormask.c
src/gallium/drivers/softpipe/sp_quad_coverage.c
src/gallium/drivers/softpipe/sp_quad_depth_test.c
src/gallium/drivers/softpipe/sp_quad_earlyz.c
src/gallium/drivers/softpipe/sp_quad_fs.c
src/gallium/drivers/softpipe/sp_quad_occlusion.c
src/gallium/drivers/softpipe/sp_quad_output.c
src/gallium/drivers/softpipe/sp_quad_pipe.c
src/gallium/drivers/softpipe/sp_quad_pipe.h
src/gallium/drivers/softpipe/sp_quad_stencil.c
src/gallium/drivers/softpipe/sp_quad_stipple.c
src/gallium/drivers/softpipe/sp_setup.c

index 0845bae0e687207f86b57d61e2928ac9e264cb95..3a282208b6b8a767a43c46fbef40cb41f934ab36 100644 (file)
@@ -9,76 +9,80 @@
 #include "pipe/p_defines.h"
 #include "util/u_memory.h"
 
+#define ALPHATEST( FUNC, COMP )                                         \
+   static void                                                          \
+   alpha_test_quads_##FUNC( struct quad_stage *qs,                      \
+                           struct quad_header *quads[],                 \
+                           unsigned nr )                                \
+   {                                                                    \
+      const float ref = qs->softpipe->depth_stencil->alpha.ref_value;   \
+      const uint cbuf = 0; /* only output[0].alpha is tested */         \
+      unsigned pass_nr = 0;                                             \
+      unsigned i;                                                       \
+                                                                        \
+      for (i = 0; i < nr; i++) {                                        \
+         const float *aaaa = quads[i]->output.color[cbuf][3];           \
+         unsigned passMask = 0;                                         \
+                                                                        \
+         if (aaaa[0] COMP ref) passMask |= (1 << 0);                    \
+         if (aaaa[1] COMP ref) passMask |= (1 << 1);                    \
+         if (aaaa[2] COMP ref) passMask |= (1 << 2);                    \
+         if (aaaa[3] COMP ref) passMask |= (1 << 3);                    \
+                                                                        \
+         quads[i]->inout.mask &= passMask;                              \
+                                                                        \
+         if (quads[i]->inout.mask)                                      \
+            quads[pass_nr++] = quads[i];                                \
+      }                                                                 \
+                                                                        \
+      if (pass_nr)                                                      \
+         qs->next->run(qs->next, quads, pass_nr);                       \
+   }
+
+
+ALPHATEST( LESS,     < )
+ALPHATEST( EQUAL,    == )
+ALPHATEST( LEQUAL,   <= )
+ALPHATEST( GREATER,  > )
+ALPHATEST( NOTEQUAL, != )
+ALPHATEST( GEQUAL,   >= )
 
+
+/* XXX: Incorporate into shader using KILP.
+ */
 static void
-alpha_test_quad(struct quad_stage *qs, struct quad_header *quad)
+alpha_test_quad(struct quad_stage *qs, 
+                struct quad_header *quads[], 
+                unsigned nr)
 {
-   struct softpipe_context *softpipe = qs->softpipe;
-   const float ref = softpipe->depth_stencil->alpha.ref_value;
-   unsigned passMask = 0x0, j;
-   const uint cbuf = 0; /* only output[0].alpha is tested */
-   const float *aaaa = quad->output.color[cbuf][3];
-
-   switch (softpipe->depth_stencil->alpha.func) {
-   case PIPE_FUNC_NEVER:
-      break;
+   switch (qs->softpipe->depth_stencil->alpha.func) {
    case PIPE_FUNC_LESS:
-      /*
-       * If mask were an array [4] we could do this SIMD-style:
-       * passMask = (quad->outputs.color[0][3] <= vec4(ref));
-       */
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (aaaa[j] < ref) {
-            passMask |= (1 << j);
-         }
-      }
+      alpha_test_quads_LESS( qs, quads, nr );
       break;
    case PIPE_FUNC_EQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (aaaa[j] == ref) {
-            passMask |= (1 << j);
-         }
-      }
+      alpha_test_quads_EQUAL( qs, quads, nr );
       break;
    case PIPE_FUNC_LEQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (aaaa[j] <= ref) {
-            passMask |= (1 << j);
-         }
-      }
+      alpha_test_quads_LEQUAL( qs, quads, nr );
       break;
    case PIPE_FUNC_GREATER:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (aaaa[j] > ref) {
-            passMask |= (1 << j);
-         }
-      }
+      alpha_test_quads_GREATER( qs, quads, nr );
       break;
    case PIPE_FUNC_NOTEQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (aaaa[j] != ref) {
-            passMask |= (1 << j);
-         }
-      }
+      alpha_test_quads_NOTEQUAL( qs, quads, nr );
       break;
    case PIPE_FUNC_GEQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (aaaa[j] >= ref) {
-            passMask |= (1 << j);
-         }
-      }
+      alpha_test_quads_GEQUAL( qs, quads, nr );
       break;
    case PIPE_FUNC_ALWAYS:
-      passMask = MASK_ALL;
+      assert(0); /* should be caught earlier */
+      qs->next->run(qs->next, quads, nr);
       break;
+   case PIPE_FUNC_NEVER:
    default:
-      assert(0);
+      assert(0); /* should be caught earlier */
+      return;
    }
-
-   quad->inout.mask &= passMask;
-
-   if (quad->inout.mask)
-      qs->next->run(qs->next, quad);
 }
 
 
index 04b5daf3a417b4f1f7a5e71eefde3c2d2a66591e..fdf1bb4552296a47573680206e69b91419950d12 100644 (file)
@@ -117,10 +117,16 @@ do { \
 
 
 static void
-logicop_quad(struct quad_stage *qs, struct quad_header *quad)
+logicop_quad(struct quad_stage *qs, 
+             struct quad_header *quads[],
+             unsigned nr)
 {
    struct softpipe_context *softpipe = qs->softpipe;
    uint cbuf;
+   struct softpipe_cached_tile *
+      tile = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
+                                quads[0]->input.x0, 
+                                quads[0]->input.y0);
 
    /* loop over colorbuffer outputs */
    for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
@@ -129,165 +135,161 @@ logicop_quad(struct quad_stage *qs, struct quad_header *quad)
       uint *src4 = (uint *) src;
       uint *dst4 = (uint *) dst;
       uint *res4 = (uint *) res;
-      struct softpipe_cached_tile *
-         tile = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
-                                   quad->input.x0, quad->input.y0);
-      float (*quadColor)[4] = quad->output.color[cbuf];
       uint i, j;
 
-      /* get/swizzle dest colors */
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
-         int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
-         for (i = 0; i < 4; i++) {
-            dest[i][j] = tile->data.color[y][x][i];
+      for (i = 0; i < nr; i++) {
+         struct quad_header *quad = quads[i];
+         float (*quadColor)[4] = quad->output.color[cbuf];
+
+         /* get/swizzle dest colors */
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
+            int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
+            for (i = 0; i < 4; i++) {
+               dest[i][j] = tile->data.color[y][x][i];
+            }
          }
-      }
 
-      /* convert to ubyte */
-      for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
-         dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
-         dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
-         dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
-         dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
-
-         src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
-         src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
-         src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
-         src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
-      }
+         /* convert to ubyte */
+         for (j = 0; j < 4; j++) { /* loop over R,G,B,A channels */
+            dst[j][0] = float_to_ubyte(dest[j][0]); /* P0 */
+            dst[j][1] = float_to_ubyte(dest[j][1]); /* P1 */
+            dst[j][2] = float_to_ubyte(dest[j][2]); /* P2 */
+            dst[j][3] = float_to_ubyte(dest[j][3]); /* P3 */
+
+            src[j][0] = float_to_ubyte(quadColor[j][0]); /* P0 */
+            src[j][1] = float_to_ubyte(quadColor[j][1]); /* P1 */
+            src[j][2] = float_to_ubyte(quadColor[j][2]); /* P2 */
+            src[j][3] = float_to_ubyte(quadColor[j][3]); /* P3 */
+         }
 
-      switch (softpipe->blend->logicop_func) {
-      case PIPE_LOGICOP_CLEAR:
-         for (j = 0; j < 4; j++)
-            res4[j] = 0;
-         break;
-      case PIPE_LOGICOP_NOR:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~(src4[j] | dst4[j]);
-         break;
-      case PIPE_LOGICOP_AND_INVERTED:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~src4[j] & dst4[j];
-         break;
-      case PIPE_LOGICOP_COPY_INVERTED:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~src4[j];
-         break;
-      case PIPE_LOGICOP_AND_REVERSE:
-         for (j = 0; j < 4; j++)
-            res4[j] = src4[j] & ~dst4[j];
-         break;
-      case PIPE_LOGICOP_INVERT:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~dst4[j];
-         break;
-      case PIPE_LOGICOP_XOR:
-         for (j = 0; j < 4; j++)
-            res4[j] = dst4[j] ^ src4[j];
-         break;
-      case PIPE_LOGICOP_NAND:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~(src4[j] & dst4[j]);
-         break;
-      case PIPE_LOGICOP_AND:
-         for (j = 0; j < 4; j++)
-            res4[j] = src4[j] & dst4[j];
-         break;
-      case PIPE_LOGICOP_EQUIV:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~(src4[j] ^ dst4[j]);
-         break;
-      case PIPE_LOGICOP_NOOP:
-         for (j = 0; j < 4; j++)
-            res4[j] = dst4[j];
-         break;
-      case PIPE_LOGICOP_OR_INVERTED:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~src4[j] | dst4[j];
-         break;
-      case PIPE_LOGICOP_COPY:
-         for (j = 0; j < 4; j++)
-            res4[j] = src4[j];
-         break;
-      case PIPE_LOGICOP_OR_REVERSE:
-         for (j = 0; j < 4; j++)
-            res4[j] = src4[j] | ~dst4[j];
-         break;
-      case PIPE_LOGICOP_OR:
-         for (j = 0; j < 4; j++)
-            res4[j] = src4[j] | dst4[j];
-         break;
-      case PIPE_LOGICOP_SET:
-         for (j = 0; j < 4; j++)
-            res4[j] = ~0;
-         break;
-      default:
-         assert(0);
-      }
+         switch (softpipe->blend->logicop_func) {
+         case PIPE_LOGICOP_CLEAR:
+            for (j = 0; j < 4; j++)
+               res4[j] = 0;
+            break;
+         case PIPE_LOGICOP_NOR:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~(src4[j] | dst4[j]);
+            break;
+         case PIPE_LOGICOP_AND_INVERTED:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~src4[j] & dst4[j];
+            break;
+         case PIPE_LOGICOP_COPY_INVERTED:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~src4[j];
+            break;
+         case PIPE_LOGICOP_AND_REVERSE:
+            for (j = 0; j < 4; j++)
+               res4[j] = src4[j] & ~dst4[j];
+            break;
+         case PIPE_LOGICOP_INVERT:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~dst4[j];
+            break;
+         case PIPE_LOGICOP_XOR:
+            for (j = 0; j < 4; j++)
+               res4[j] = dst4[j] ^ src4[j];
+            break;
+         case PIPE_LOGICOP_NAND:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~(src4[j] & dst4[j]);
+            break;
+         case PIPE_LOGICOP_AND:
+            for (j = 0; j < 4; j++)
+               res4[j] = src4[j] & dst4[j];
+            break;
+         case PIPE_LOGICOP_EQUIV:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~(src4[j] ^ dst4[j]);
+            break;
+         case PIPE_LOGICOP_NOOP:
+            for (j = 0; j < 4; j++)
+               res4[j] = dst4[j];
+            break;
+         case PIPE_LOGICOP_OR_INVERTED:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~src4[j] | dst4[j];
+            break;
+         case PIPE_LOGICOP_COPY:
+            for (j = 0; j < 4; j++)
+               res4[j] = src4[j];
+            break;
+         case PIPE_LOGICOP_OR_REVERSE:
+            for (j = 0; j < 4; j++)
+               res4[j] = src4[j] | ~dst4[j];
+            break;
+         case PIPE_LOGICOP_OR:
+            for (j = 0; j < 4; j++)
+               res4[j] = src4[j] | dst4[j];
+            break;
+         case PIPE_LOGICOP_SET:
+            for (j = 0; j < 4; j++)
+               res4[j] = ~0;
+            break;
+         default:
+            assert(0);
+         }
 
-      for (j = 0; j < 4; j++) {
-         quadColor[j][0] = ubyte_to_float(res[j][0]);
-         quadColor[j][1] = ubyte_to_float(res[j][1]);
-         quadColor[j][2] = ubyte_to_float(res[j][2]);
-         quadColor[j][3] = ubyte_to_float(res[j][3]);
+         for (j = 0; j < 4; j++) {
+            quadColor[j][0] = ubyte_to_float(res[j][0]);
+            quadColor[j][1] = ubyte_to_float(res[j][1]);
+            quadColor[j][2] = ubyte_to_float(res[j][2]);
+            quadColor[j][3] = ubyte_to_float(res[j][3]);
+         }
       }
    }
-
-   /* pass quad to next stage */
-   qs->next->run(qs->next, quad);
 }
 
 
-
-
 static void
-blend_quad(struct quad_stage *qs, struct quad_header *quad)
+blend_quads(struct quad_stage *qs, 
+            struct quad_header *quads[],
+            unsigned nr)
 {
    static const float zero[4] = { 0, 0, 0, 0 };
    static const float one[4] = { 1, 1, 1, 1 };
-
    struct softpipe_context *softpipe = qs->softpipe;
    uint cbuf;
 
-   if (softpipe->blend->logicop_enable) {
-      logicop_quad(qs, quad);
-      return;
-   }
-
    /* loop over colorbuffer outputs */
    for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
       float source[4][QUAD_SIZE], dest[4][QUAD_SIZE];
       struct softpipe_cached_tile *tile
          = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
-                              quad->input.x0, quad->input.y0);
-      float (*quadColor)[4] = quad->output.color[cbuf];
-      uint i, j;
-
-      /* get/swizzle dest colors */
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
-         int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
-         for (i = 0; i < 4; i++) {
-            dest[i][j] = tile->data.color[y][x][i];
+                              quads[0]->input.x0, 
+                              quads[0]->input.y0);
+      uint q, i, j;
+
+      for (q = 0; q < nr; q++) {
+         struct quad_header *quad = quads[q];
+         float (*quadColor)[4] = quad->output.color[cbuf];
+
+         /* get/swizzle dest colors */
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = (quad->input.x0 & (TILE_SIZE-1)) + (j & 1);
+            int y = (quad->input.y0 & (TILE_SIZE-1)) + (j >> 1);
+            for (i = 0; i < 4; i++) {
+               dest[i][j] = tile->data.color[y][x][i];
+            }
          }
-      }
 
-      /*
-       * Compute src/first term RGB
-       */
-      switch (softpipe->blend->rgb_src_factor) {
-      case PIPE_BLENDFACTOR_ONE:
-         VEC4_COPY(source[0], quadColor[0]); /* R */
-         VEC4_COPY(source[1], quadColor[1]); /* G */
-         VEC4_COPY(source[2], quadColor[2]); /* B */
-         break;
-      case PIPE_BLENDFACTOR_SRC_COLOR:
-         VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
-         VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
-         VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
-         break;
-      case PIPE_BLENDFACTOR_SRC_ALPHA:
+         /*
+          * Compute src/first term RGB
+          */
+         switch (softpipe->blend->rgb_src_factor) {
+         case PIPE_BLENDFACTOR_ONE:
+            VEC4_COPY(source[0], quadColor[0]); /* R */
+            VEC4_COPY(source[1], quadColor[1]); /* G */
+            VEC4_COPY(source[2], quadColor[2]); /* B */
+            break;
+         case PIPE_BLENDFACTOR_SRC_COLOR:
+            VEC4_MUL(source[0], quadColor[0], quadColor[0]); /* R */
+            VEC4_MUL(source[1], quadColor[1], quadColor[1]); /* G */
+            VEC4_MUL(source[2], quadColor[2], quadColor[2]); /* B */
+            break;
+         case PIPE_BLENDFACTOR_SRC_ALPHA:
          {
             const float *alpha = quadColor[3];
             VEC4_MUL(source[0], quadColor[0], alpha); /* R */
@@ -295,12 +297,12 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], alpha); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_DST_COLOR:
-         VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
-         VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
-         VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
-         break;
-      case PIPE_BLENDFACTOR_DST_ALPHA:
+         case PIPE_BLENDFACTOR_DST_COLOR:
+            VEC4_MUL(source[0], quadColor[0], dest[0]); /* R */
+            VEC4_MUL(source[1], quadColor[1], dest[1]); /* G */
+            VEC4_MUL(source[2], quadColor[2], dest[2]); /* B */
+            break;
+         case PIPE_BLENDFACTOR_DST_ALPHA:
          {
             const float *alpha = dest[3];
             VEC4_MUL(source[0], quadColor[0], alpha); /* R */
@@ -308,7 +310,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], alpha); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+         case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
          {
             const float *alpha = quadColor[3];
             float diff[4], temp[4];
@@ -319,7 +321,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], temp); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_CONST_COLOR:
+         case PIPE_BLENDFACTOR_CONST_COLOR:
          {
             float comp[4];
             VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
@@ -330,7 +332,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], comp); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_CONST_ALPHA:
+         case PIPE_BLENDFACTOR_CONST_ALPHA:
          {
             float alpha[4];
             VEC4_SCALAR(alpha, softpipe->blend_color.color[3]);
@@ -339,18 +341,18 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], alpha); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_SRC1_COLOR:
-         assert(0); /* to do */
-         break;
-      case PIPE_BLENDFACTOR_SRC1_ALPHA:
-         assert(0); /* to do */
-         break;
-      case PIPE_BLENDFACTOR_ZERO:
-         VEC4_COPY(source[0], zero); /* R */
-         VEC4_COPY(source[1], zero); /* G */
-         VEC4_COPY(source[2], zero); /* B */
-         break;
-      case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+         case PIPE_BLENDFACTOR_SRC1_COLOR:
+            assert(0); /* to do */
+            break;
+         case PIPE_BLENDFACTOR_SRC1_ALPHA:
+            assert(0); /* to do */
+            break;
+         case PIPE_BLENDFACTOR_ZERO:
+            VEC4_COPY(source[0], zero); /* R */
+            VEC4_COPY(source[1], zero); /* G */
+            VEC4_COPY(source[2], zero); /* B */
+            break;
+         case PIPE_BLENDFACTOR_INV_SRC_COLOR:
          {
             float inv_comp[4];
             VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
@@ -361,7 +363,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+         case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
          {
             float inv_alpha[4];
             VEC4_SUB(inv_alpha, one, quadColor[3]);
@@ -370,7 +372,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_DST_ALPHA:
          {
             float inv_alpha[4];
             VEC4_SUB(inv_alpha, one, dest[3]);
@@ -379,7 +381,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_DST_COLOR:
+         case PIPE_BLENDFACTOR_INV_DST_COLOR:
          {
             float inv_comp[4];
             VEC4_SUB(inv_comp, one, dest[0]); /* R */
@@ -390,7 +392,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], inv_comp); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+         case PIPE_BLENDFACTOR_INV_CONST_COLOR:
          {
             float inv_comp[4];
             /* R */
@@ -404,7 +406,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], inv_comp);
          }
          break;
-      case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
          {
             float inv_alpha[4];
             VEC4_SCALAR(inv_alpha, 1.0f - softpipe->blend_color.color[3]);
@@ -413,73 +415,73 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[2], quadColor[2], inv_alpha); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
-         assert(0); /* to do */
-         break;
-      case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
-         assert(0); /* to do */
-         break;
-      default:
-         assert(0);
-      }
+         case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+            assert(0); /* to do */
+            break;
+         case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+            assert(0); /* to do */
+            break;
+         default:
+            assert(0);
+         }
 
-      /*
-       * Compute src/first term A
-       */
-      switch (softpipe->blend->alpha_src_factor) {
-      case PIPE_BLENDFACTOR_ONE:
-         VEC4_COPY(source[3], quadColor[3]); /* A */
-         break;
-      case PIPE_BLENDFACTOR_SRC_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_SRC_ALPHA:
+         /*
+          * Compute src/first term A
+          */
+         switch (softpipe->blend->alpha_src_factor) {
+         case PIPE_BLENDFACTOR_ONE:
+            VEC4_COPY(source[3], quadColor[3]); /* A */
+            break;
+         case PIPE_BLENDFACTOR_SRC_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_SRC_ALPHA:
          {
             const float *alpha = quadColor[3];
             VEC4_MUL(source[3], quadColor[3], alpha); /* A */
          }
          break;
-      case PIPE_BLENDFACTOR_DST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_DST_ALPHA:
-         VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
-         break;
-      case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
-         /* multiply alpha by 1.0 */
-         VEC4_COPY(source[3], quadColor[3]); /* A */
-         break;
-      case PIPE_BLENDFACTOR_CONST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_CONST_ALPHA:
+         case PIPE_BLENDFACTOR_DST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_DST_ALPHA:
+            VEC4_MUL(source[3], quadColor[3], dest[3]); /* A */
+            break;
+         case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+            /* multiply alpha by 1.0 */
+            VEC4_COPY(source[3], quadColor[3]); /* A */
+            break;
+         case PIPE_BLENDFACTOR_CONST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_CONST_ALPHA:
          {
             float comp[4];
             VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
             VEC4_MUL(source[3], quadColor[3], comp); /* A */
          }
          break;
-      case PIPE_BLENDFACTOR_ZERO:
-         VEC4_COPY(source[3], zero); /* A */
-         break;
-      case PIPE_BLENDFACTOR_INV_SRC_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+         case PIPE_BLENDFACTOR_ZERO:
+            VEC4_COPY(source[3], zero); /* A */
+            break;
+         case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
          {
             float inv_alpha[4];
             VEC4_SUB(inv_alpha, one, quadColor[3]);
             VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_DST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_DST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_INV_DST_ALPHA:
          {
             float inv_alpha[4];
             VEC4_SUB(inv_alpha, one, dest[3]);
             VEC4_MUL(source[3], quadColor[3], inv_alpha); /* A */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_CONST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
          {
             float inv_comp[4];
             /* A */
@@ -487,42 +489,42 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(source[3], quadColor[3], inv_comp);
          }
          break;
-      default:
-         assert(0);
-      }
+         default:
+            assert(0);
+         }
 
 
-      /*
-       * Compute dest/second term RGB
-       */
-      switch (softpipe->blend->rgb_dst_factor) {
-      case PIPE_BLENDFACTOR_ONE:
-         /* dest = dest * 1   NO-OP, leave dest as-is */
-         break;
-      case PIPE_BLENDFACTOR_SRC_COLOR:
-         VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */
-         VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */
-         VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */
-         break;
-      case PIPE_BLENDFACTOR_SRC_ALPHA:
-         VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */
-         VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */
-         VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */
-         break;
-      case PIPE_BLENDFACTOR_DST_ALPHA:
-         VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
-         VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
-         VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
-         break;
-      case PIPE_BLENDFACTOR_DST_COLOR:
-         VEC4_MUL(dest[0], dest[0], dest[0]); /* R */
-         VEC4_MUL(dest[1], dest[1], dest[1]); /* G */
-         VEC4_MUL(dest[2], dest[2], dest[2]); /* B */
-         break;
-      case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
-         assert(0); /* illegal */
-         break;
-      case PIPE_BLENDFACTOR_CONST_COLOR:
+         /*
+          * Compute dest/second term RGB
+          */
+         switch (softpipe->blend->rgb_dst_factor) {
+         case PIPE_BLENDFACTOR_ONE:
+            /* dest = dest * 1   NO-OP, leave dest as-is */
+            break;
+         case PIPE_BLENDFACTOR_SRC_COLOR:
+            VEC4_MUL(dest[0], dest[0], quadColor[0]); /* R */
+            VEC4_MUL(dest[1], dest[1], quadColor[1]); /* G */
+            VEC4_MUL(dest[2], dest[2], quadColor[2]); /* B */
+            break;
+         case PIPE_BLENDFACTOR_SRC_ALPHA:
+            VEC4_MUL(dest[0], dest[0], quadColor[3]); /* R * A */
+            VEC4_MUL(dest[1], dest[1], quadColor[3]); /* G * A */
+            VEC4_MUL(dest[2], dest[2], quadColor[3]); /* B * A */
+            break;
+         case PIPE_BLENDFACTOR_DST_ALPHA:
+            VEC4_MUL(dest[0], dest[0], dest[3]); /* R * A */
+            VEC4_MUL(dest[1], dest[1], dest[3]); /* G * A */
+            VEC4_MUL(dest[2], dest[2], dest[3]); /* B * A */
+            break;
+         case PIPE_BLENDFACTOR_DST_COLOR:
+            VEC4_MUL(dest[0], dest[0], dest[0]); /* R */
+            VEC4_MUL(dest[1], dest[1], dest[1]); /* G */
+            VEC4_MUL(dest[2], dest[2], dest[2]); /* B */
+            break;
+         case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+            assert(0); /* illegal */
+            break;
+         case PIPE_BLENDFACTOR_CONST_COLOR:
          {
             float comp[4];
             VEC4_SCALAR(comp, softpipe->blend_color.color[0]); /* R */
@@ -533,7 +535,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], dest[2], comp); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_CONST_ALPHA:
+         case PIPE_BLENDFACTOR_CONST_ALPHA:
          {
             float comp[4];
             VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
@@ -542,17 +544,17 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], dest[2], comp); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_ZERO:
-         VEC4_COPY(dest[0], zero); /* R */
-         VEC4_COPY(dest[1], zero); /* G */
-         VEC4_COPY(dest[2], zero); /* B */
-         break;
-      case PIPE_BLENDFACTOR_SRC1_COLOR:
-      case PIPE_BLENDFACTOR_SRC1_ALPHA:
-         /* XXX what are these? */
-         assert(0);
-         break;
-      case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+         case PIPE_BLENDFACTOR_ZERO:
+            VEC4_COPY(dest[0], zero); /* R */
+            VEC4_COPY(dest[1], zero); /* G */
+            VEC4_COPY(dest[2], zero); /* B */
+            break;
+         case PIPE_BLENDFACTOR_SRC1_COLOR:
+         case PIPE_BLENDFACTOR_SRC1_ALPHA:
+            /* XXX what are these? */
+            assert(0);
+            break;
+         case PIPE_BLENDFACTOR_INV_SRC_COLOR:
          {
             float inv_comp[4];
             VEC4_SUB(inv_comp, one, quadColor[0]); /* R */
@@ -563,7 +565,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+         case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
          {
             float one_minus_alpha[QUAD_SIZE];
             VEC4_SUB(one_minus_alpha, one, quadColor[3]);
@@ -572,7 +574,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], dest[2], one_minus_alpha); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_DST_ALPHA:
          {
             float inv_comp[4];
             VEC4_SUB(inv_comp, one, dest[3]); /* A */
@@ -581,7 +583,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], inv_comp, dest[2]); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_DST_COLOR:
+         case PIPE_BLENDFACTOR_INV_DST_COLOR:
          {
             float inv_comp[4];
             VEC4_SUB(inv_comp, one, dest[0]); /* R */
@@ -592,7 +594,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], dest[2], inv_comp); /* B */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+         case PIPE_BLENDFACTOR_INV_CONST_COLOR:
          {
             float inv_comp[4];
             /* R */
@@ -606,7 +608,7 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], dest[2], inv_comp);
          }
          break;
-      case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
          {
             float inv_comp[4];
             VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
@@ -615,138 +617,154 @@ blend_quad(struct quad_stage *qs, struct quad_header *quad)
             VEC4_MUL(dest[2], dest[2], inv_comp);
          }
          break;
-      case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
-      case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
-         /* XXX what are these? */
-         assert(0);
-         break;
-      default:
-         assert(0);
-      }
+         case PIPE_BLENDFACTOR_INV_SRC1_COLOR:
+         case PIPE_BLENDFACTOR_INV_SRC1_ALPHA:
+            /* XXX what are these? */
+            assert(0);
+            break;
+         default:
+            assert(0);
+         }
 
-      /*
-       * Compute dest/second term A
-       */
-      switch (softpipe->blend->alpha_dst_factor) {
-      case PIPE_BLENDFACTOR_ONE:
-         /* dest = dest * 1   NO-OP, leave dest as-is */
-         break;
-      case PIPE_BLENDFACTOR_SRC_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_SRC_ALPHA:
-         VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
-         break;
-      case PIPE_BLENDFACTOR_DST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_DST_ALPHA:
-         VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
-         break;
-      case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
-         assert(0); /* illegal */
-         break;
-      case PIPE_BLENDFACTOR_CONST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_CONST_ALPHA:
+         /*
+          * Compute dest/second term A
+          */
+         switch (softpipe->blend->alpha_dst_factor) {
+         case PIPE_BLENDFACTOR_ONE:
+            /* dest = dest * 1   NO-OP, leave dest as-is */
+            break;
+         case PIPE_BLENDFACTOR_SRC_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_SRC_ALPHA:
+            VEC4_MUL(dest[3], dest[3], quadColor[3]); /* A * A */
+            break;
+         case PIPE_BLENDFACTOR_DST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_DST_ALPHA:
+            VEC4_MUL(dest[3], dest[3], dest[3]); /* A */
+            break;
+         case PIPE_BLENDFACTOR_SRC_ALPHA_SATURATE:
+            assert(0); /* illegal */
+            break;
+         case PIPE_BLENDFACTOR_CONST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_CONST_ALPHA:
          {
             float comp[4];
             VEC4_SCALAR(comp, softpipe->blend_color.color[3]); /* A */
             VEC4_MUL(dest[3], dest[3], comp); /* A */
          }
          break;
-      case PIPE_BLENDFACTOR_ZERO:
-         VEC4_COPY(dest[3], zero); /* A */
-         break;
-      case PIPE_BLENDFACTOR_INV_SRC_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
+         case PIPE_BLENDFACTOR_ZERO:
+            VEC4_COPY(dest[3], zero); /* A */
+            break;
+         case PIPE_BLENDFACTOR_INV_SRC_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_INV_SRC_ALPHA:
          {
             float one_minus_alpha[QUAD_SIZE];
             VEC4_SUB(one_minus_alpha, one, quadColor[3]);
             VEC4_MUL(dest[3], dest[3], one_minus_alpha); /* A */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_DST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_INV_DST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_DST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_INV_DST_ALPHA:
          {
             float inv_comp[4];
             VEC4_SUB(inv_comp, one, dest[3]); /* A */
             VEC4_MUL(dest[3], inv_comp, dest[3]); /* A */
          }
          break;
-      case PIPE_BLENDFACTOR_INV_CONST_COLOR:
-         /* fall-through */
-      case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
+         case PIPE_BLENDFACTOR_INV_CONST_COLOR:
+            /* fall-through */
+         case PIPE_BLENDFACTOR_INV_CONST_ALPHA:
          {
             float inv_comp[4];
             VEC4_SCALAR(inv_comp, 1.0f - softpipe->blend_color.color[3]);
             VEC4_MUL(dest[3], dest[3], inv_comp);
          }
          break;
-      default:
-         assert(0);
-      }
+         default:
+            assert(0);
+         }
 
-      /*
-       * Combine RGB terms
-       */
-      switch (softpipe->blend->rgb_func) {
-      case PIPE_BLEND_ADD:
-         VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */
-         VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */
-         VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */
-         break;
-      case PIPE_BLEND_SUBTRACT:
-         VEC4_SUB_SAT(quadColor[0], source[0], dest[0]); /* R */
-         VEC4_SUB_SAT(quadColor[1], source[1], dest[1]); /* G */
-         VEC4_SUB_SAT(quadColor[2], source[2], dest[2]); /* B */
-         break;
-      case PIPE_BLEND_REVERSE_SUBTRACT:
-         VEC4_SUB_SAT(quadColor[0], dest[0], source[0]); /* R */
-         VEC4_SUB_SAT(quadColor[1], dest[1], source[1]); /* G */
-         VEC4_SUB_SAT(quadColor[2], dest[2], source[2]); /* B */
-         break;
-      case PIPE_BLEND_MIN:
-         VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */
-         VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */
-         VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */
-         break;
-      case PIPE_BLEND_MAX:
-         VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */
-         VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */
-         VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */
-         break;
-      default:
-         assert(0);
-      }
+         /*
+          * Combine RGB terms
+          */
+         switch (softpipe->blend->rgb_func) {
+         case PIPE_BLEND_ADD:
+            VEC4_ADD_SAT(quadColor[0], source[0], dest[0]); /* R */
+            VEC4_ADD_SAT(quadColor[1], source[1], dest[1]); /* G */
+            VEC4_ADD_SAT(quadColor[2], source[2], dest[2]); /* B */
+            break;
+         case PIPE_BLEND_SUBTRACT:
+            VEC4_SUB_SAT(quadColor[0], source[0], dest[0]); /* R */
+            VEC4_SUB_SAT(quadColor[1], source[1], dest[1]); /* G */
+            VEC4_SUB_SAT(quadColor[2], source[2], dest[2]); /* B */
+            break;
+         case PIPE_BLEND_REVERSE_SUBTRACT:
+            VEC4_SUB_SAT(quadColor[0], dest[0], source[0]); /* R */
+            VEC4_SUB_SAT(quadColor[1], dest[1], source[1]); /* G */
+            VEC4_SUB_SAT(quadColor[2], dest[2], source[2]); /* B */
+            break;
+         case PIPE_BLEND_MIN:
+            VEC4_MIN(quadColor[0], source[0], dest[0]); /* R */
+            VEC4_MIN(quadColor[1], source[1], dest[1]); /* G */
+            VEC4_MIN(quadColor[2], source[2], dest[2]); /* B */
+            break;
+         case PIPE_BLEND_MAX:
+            VEC4_MAX(quadColor[0], source[0], dest[0]); /* R */
+            VEC4_MAX(quadColor[1], source[1], dest[1]); /* G */
+            VEC4_MAX(quadColor[2], source[2], dest[2]); /* B */
+            break;
+         default:
+            assert(0);
+         }
 
-      /*
-       * Combine A terms
-       */
-      switch (softpipe->blend->alpha_func) {
-      case PIPE_BLEND_ADD:
-         VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
-         break;
-      case PIPE_BLEND_SUBTRACT:
-         VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */
-         break;
-      case PIPE_BLEND_REVERSE_SUBTRACT:
-         VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */
-         break;
-      case PIPE_BLEND_MIN:
-         VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
-         break;
-      case PIPE_BLEND_MAX:
-         VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
-         break;
-      default:
-         assert(0);
+         /*
+          * Combine A terms
+          */
+         switch (softpipe->blend->alpha_func) {
+         case PIPE_BLEND_ADD:
+            VEC4_ADD_SAT(quadColor[3], source[3], dest[3]); /* A */
+            break;
+         case PIPE_BLEND_SUBTRACT:
+            VEC4_SUB_SAT(quadColor[3], source[3], dest[3]); /* A */
+            break;
+         case PIPE_BLEND_REVERSE_SUBTRACT:
+            VEC4_SUB_SAT(quadColor[3], dest[3], source[3]); /* A */
+            break;
+         case PIPE_BLEND_MIN:
+            VEC4_MIN(quadColor[3], source[3], dest[3]); /* A */
+            break;
+         case PIPE_BLEND_MAX:
+            VEC4_MAX(quadColor[3], source[3], dest[3]); /* A */
+            break;
+         default:
+            assert(0);
+         }
       }
-
    } /* cbuf loop */
+}
+
+
+static void
+blend_quad(struct quad_stage *qs, 
+           struct quad_header *quads[],
+           unsigned nr)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+
+   if (softpipe->blend->logicop_enable) {
+      logicop_quad(qs, quads, nr);
+   }
+   else if (softpipe->blend->blend_enable) {
+      blend_quads(qs, quads, nr );
+   }
 
    /* pass blended quad to next stage */
-   qs->next->run(qs->next, quad);
+   qs->next->run(qs->next, quads, nr);
 }
 
 
index 89efbe3b02490ac93747e08f47b94bd7a6778b67..ac74287473349bca398b70d07ba402138625b0e0 100644 (file)
@@ -84,12 +84,23 @@ colormask_quad(struct quad_stage *qs, struct quad_header *quad)
       if (!(softpipe->blend->colormask & PIPE_MASK_A))
           COPY_4V(quadColor[3], dest[3]);
    }
+}
+
+static void
+colormask_quads(struct quad_stage *qs, struct quad_header *quads[],
+                unsigned nr)
+{
+   unsigned i;
+
+   for (i = 0; i < nr; i++)
+      colormask_quad(qs, quads[i]);
 
    /* pass quad to next stage */
-   qs->next->run(qs->next, quad);
+   qs->next->run(qs->next, quads, nr);
 }
 
 
+
 static void colormask_begin(struct quad_stage *qs)
 {
    qs->next->begin(qs->next);
@@ -108,7 +119,7 @@ struct quad_stage *sp_quad_colormask_stage( struct softpipe_context *softpipe )
 
    stage->softpipe = softpipe;
    stage->begin = colormask_begin;
-   stage->run = colormask_quad;
+   stage->run = colormask_quads;
    stage->destroy = colormask_destroy;
 
    return stage;
index 4aeee858705184736b49011db46fd358c0d7c0e2..eda5ce8e630c015b6078a51cc8a2566ac0a26cc9 100644 (file)
 /**
  * Multiply quad's alpha values by the fragment coverage.
  */
-static void
+static INLINE void
 coverage_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
-   const uint prim = quad->input.prim;
+   uint cbuf;
+
+   /* loop over colorbuffer outputs */
+   for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
+      float (*quadColor)[4] = quad->output.color[cbuf];
+      unsigned j;
+      for (j = 0; j < QUAD_SIZE; j++) {
+         assert(quad->input.coverage[j] >= 0.0);
+         assert(quad->input.coverage[j] <= 1.0);
+         quadColor[3][j] *= quad->input.coverage[j];
+      }
+   }
+}
+
+
+/* XXX: Incorporate into shader after alpha_test.
+ */
+static void
+coverage_run(struct quad_stage *qs,
+               struct quad_header *quads[],
+               unsigned nr)
+{
+   struct softpipe_context *softpipe = qs->softpipe;
+   const uint prim = quads[0]->input.prim;
+   unsigned i;
 
    if ((softpipe->rasterizer->poly_smooth && prim == QUAD_PRIM_TRI) ||
        (softpipe->rasterizer->line_smooth && prim == QUAD_PRIM_LINE) ||
        (softpipe->rasterizer->point_smooth && prim == QUAD_PRIM_POINT)) {
-      uint cbuf;
-
-      /* loop over colorbuffer outputs */
-      for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
-         float (*quadColor)[4] = quad->output.color[cbuf];
-         unsigned j;
-         for (j = 0; j < QUAD_SIZE; j++) {
-            assert(quad->input.coverage[j] >= 0.0);
-            assert(quad->input.coverage[j] <= 1.0);
-         quadColor[3][j] *= quad->input.coverage[j];
-         }
-      }
+
+      for (i = 0; i < nr; i++)
+         coverage_quad( qs, quads[i] );
    }
 
-   qs->next->run(qs->next, quad);
+   qs->next->run(qs->next, quads, nr);
 }
 
-
 static void coverage_begin(struct quad_stage *qs)
 {
    qs->next->begin(qs->next);
@@ -87,7 +101,7 @@ struct quad_stage *sp_quad_coverage_stage( struct softpipe_context *softpipe )
 
    stage->softpipe = softpipe;
    stage->begin = coverage_begin;
-   stage->run = coverage_quad;
+   stage->run = coverage_run;
    stage->destroy = coverage_destroy;
 
    return stage;
index 768b9275b30f95645e7461ff98bb92d84dd5962e..8f223a7eaeb0a50d3d503c4eaa9b7e808bab3c09 100644 (file)
@@ -49,7 +49,7 @@
  * Try to effectively do that with codegen...
  */
 
-void
+boolean
 sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
@@ -193,6 +193,8 @@ sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
    }
 
    quad->inout.mask &= zmask;
+   if (quad->inout.mask == 0)
+      return FALSE;
 
    if (softpipe->depth_stencil->depth.writemask) {
       
@@ -252,16 +254,25 @@ sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
          assert(0);
       }
    }
+
+   return TRUE;
 }
 
 
 static void
-depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+depth_test_quads(struct quad_stage *qs, 
+                 struct quad_header *quads[],
+                 unsigned nr)
 {
-   sp_depth_test_quad(qs, quad);
+   unsigned i, pass = 0;
 
-   if (quad->inout.mask)
-      qs->next->run(qs->next, quad);
+   for (i = 0; i < nr; i++) {
+      if (sp_depth_test_quad(qs, quads[i]))
+         quads[pass++] = quads[i];
+   }
+   
+   if (pass)
+      qs->next->run(qs->next, quads, pass);
 }
 
 
@@ -283,7 +294,7 @@ struct quad_stage *sp_quad_depth_test_stage( struct softpipe_context *softpipe )
 
    stage->softpipe = softpipe;
    stage->begin = depth_test_begin;
-   stage->run = depth_test_quad;
+   stage->run = depth_test_quads;
    stage->destroy = depth_test_destroy;
 
    return stage;
index 496fd39ed1ac399b48b2dc80828ce5ba3f9e18f2..1048d4498433ce585e0cb4fe6c8dd91e80a4acf5 100644 (file)
 static void
 earlyz_quad(
    struct quad_stage    *qs,
-   struct quad_header   *quad )
+   struct quad_header   *quads[],
+   unsigned nr )
 {
-   const float fx = (float) quad->input.x0;
-   const float fy = (float) quad->input.y0;
-   const float dzdx = quad->posCoef->dadx[2];
-   const float dzdy = quad->posCoef->dady[2];
-   const float z0 = quad->posCoef->a0[2] + dzdx * fx + dzdy * fy;
+   const float a0z = quads[0]->posCoef->a0[2];
+   const float dzdx = quads[0]->posCoef->dadx[2];
+   const float dzdy = quads[0]->posCoef->dady[2];
+   unsigned i;
 
-   quad->output.depth[0] = z0;
-   quad->output.depth[1] = z0 + dzdx;
-   quad->output.depth[2] = z0 + dzdy;
-   quad->output.depth[3] = z0 + dzdx + dzdy;
+   for (i = 0; i < nr; i++) {
+      const float fx = (float) quads[i]->input.x0;
+      const float fy = (float) quads[i]->input.y0;
+      const float z0 = a0z + dzdx * fx + dzdy * fy;
 
-   qs->next->run( qs->next, quad );
+      quads[i]->output.depth[0] = z0;
+      quads[i]->output.depth[1] = z0 + dzdx;
+      quads[i]->output.depth[2] = z0 + dzdy;
+      quads[i]->output.depth[3] = z0 + dzdx + dzdy;
+   }
+
+   qs->next->run( qs->next, quads, nr );
 }
 
 static void
index 28f8d1a60ea901d47b402e53f9e6b40b602dd363..ea5ed3bbd073f1f3e5853b2d73661e37680f567d 100644 (file)
@@ -68,21 +68,18 @@ quad_shade_stage(struct quad_stage *qs)
 /**
  * Execute fragment shader for the four fragments in the quad.
  */
-static void
+static boolean
 shade_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct quad_shade_stage *qss = quad_shade_stage( qs );
    struct softpipe_context *softpipe = qs->softpipe;
    struct tgsi_exec_machine *machine = qss->machine;
    boolean z_written;
-   
-   /* Consts do not require 16 byte alignment. */
-   machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
-
-   machine->InterpCoefs = quad->coef;
 
    /* run shader */
    quad->inout.mask &= softpipe->fs->run( softpipe->fs, machine, quad );
+   if (quad->inout.mask == 0)
+      return FALSE;
 
    /* store outputs */
    z_written = FALSE;
@@ -129,11 +126,34 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
       quad->output.depth[3] = z0 + dzdx + dzdy;
    }
 
-   /* shader may cull fragments */
-   if (quad->inout.mask) {
-      qs->next->run( qs->next, quad );
+   return TRUE;
+}
+
+static void
+shade_quads(struct quad_stage *qs, 
+                 struct quad_header *quads[],
+                 unsigned nr)
+{
+   struct quad_shade_stage *qss = quad_shade_stage( qs );
+   struct softpipe_context *softpipe = qs->softpipe;
+   struct tgsi_exec_machine *machine = qss->machine;
+
+   unsigned i, pass = 0;
+   
+   machine->Consts = softpipe->mapped_constants[PIPE_SHADER_FRAGMENT];
+   machine->InterpCoefs = quads[0]->coef;
+
+   for (i = 0; i < nr; i++) {
+      if (shade_quad(qs, quads[i]))
+         quads[pass++] = quads[i];
    }
+   
+   if (pass)
+      qs->next->run(qs->next, quads, pass);
 }
+   
+
+
 
 
 /**
@@ -174,7 +194,7 @@ sp_quad_shade_stage( struct softpipe_context *softpipe )
 
    qss->stage.softpipe = softpipe;
    qss->stage.begin = shade_begin;
-   qss->stage.run = shade_quad;
+   qss->stage.run = shade_quads;
    qss->stage.destroy = shade_destroy;
 
    qss->machine = tgsi_exec_machine_create();
index dfa7ff3b1d17d6fe0f2d473c87ab600e817af336..4adeb16546abb7cb3519b406911de28fedf7d7a1 100644 (file)
@@ -50,13 +50,15 @@ static unsigned count_bits( unsigned val )
 }
 
 static void
-occlusion_count_quad(struct quad_stage *qs, struct quad_header *quad)
+occlusion_count_quads(struct quad_stage *qs, struct quad_header *quads[], unsigned nr)
 {
    struct softpipe_context *softpipe = qs->softpipe;
+   unsigned i;
 
-   softpipe->occlusion_count += count_bits(quad->inout.mask);
+   for (i = 0; i < nr; i++)
+      softpipe->occlusion_count += count_bits(quads[i]->inout.mask);
 
-   qs->next->run(qs->next, quad);
+   qs->next->run(qs->next, quads, nr);
 }
 
 
@@ -78,7 +80,7 @@ struct quad_stage *sp_quad_occlusion_stage( struct softpipe_context *softpipe )
 
    stage->softpipe = softpipe;
    stage->begin = occlusion_begin;
-   stage->run = occlusion_count_quad;
+   stage->run = occlusion_count_quads;
    stage->destroy = occlusion_destroy;
 
    return stage;
index dd8f5377e91b57899938d2643040360aca442b26..79a222ff58d7f5e1a7b338acdbdac6e94b86639d 100644 (file)
  * taking mask into account.
  */
 static void
-output_quad(struct quad_stage *qs, struct quad_header *quad)
+output_quad(struct quad_stage *qs, struct quad_header *quads[], unsigned nr)
 {
-   /* in-tile pos: */
-   const int itx = quad->input.x0 % TILE_SIZE;
-   const int ity = quad->input.y0 % TILE_SIZE;
 
    struct softpipe_context *softpipe = qs->softpipe;
    uint cbuf;
@@ -51,25 +48,35 @@ output_quad(struct quad_stage *qs, struct quad_header *quad)
    for (cbuf = 0; cbuf < softpipe->framebuffer.nr_cbufs; cbuf++) {
       struct softpipe_cached_tile *tile
          = sp_get_cached_tile(softpipe->cbuf_cache[cbuf],
-                              quad->input.x0, quad->input.y0);
-      float (*quadColor)[4] = quad->output.color[cbuf];
-      int i, j;
+                              quads[0]->input.x0, 
+                              quads[0]->input.y0);
+      int i, j, q;
 
       /* get/swizzle dest colors */
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (quad->inout.mask & (1 << j)) {
-            int x = itx + (j & 1);
-            int y = ity + (j >> 1);
-            for (i = 0; i < 4; i++) { /* loop over color chans */
-               tile->data.color[y][x][i] = quadColor[i][j];
-            }
-            if (0) {
-               debug_printf("sp write pixel %d,%d: %g, %g, %g\n",
-                            quad->input.x0 + x,
-                            quad->input.y0 + y,
-                            quadColor[0][j],
-                            quadColor[1][j],
-                            quadColor[2][j]);
+      for (q = 0; q < nr; q++) {
+         struct quad_header *quad = quads[q];
+         float (*quadColor)[4] = quad->output.color[cbuf];
+
+         /* in-tile pos: */
+         const int itx = quad->input.x0 % TILE_SIZE;
+         const int ity = quad->input.y0 % TILE_SIZE;
+
+         
+         for (j = 0; j < QUAD_SIZE; j++) {
+            if (quad->inout.mask & (1 << j)) {
+               int x = itx + (j & 1);
+               int y = ity + (j >> 1);
+               for (i = 0; i < 4; i++) { /* loop over color chans */
+                  tile->data.color[y][x][i] = quadColor[i][j];
+               }
+               if (0) {
+                  debug_printf("sp write pixel %d,%d: %g, %g, %g\n",
+                               quad->input.x0 + x,
+                               quad->input.y0 + y,
+                               quadColor[0][j],
+                               quadColor[1][j],
+                               quadColor[2][j]);
+               }
             }
          }
       }
index 3a3359d303dbdf91ae6a750b2196632a5d0589c4..594fade45577e5ee3066e9b3ab345896b5cbf149 100644 (file)
@@ -55,50 +55,52 @@ void
 sp_build_quad_pipeline(struct softpipe_context *sp)
 {
    boolean early_depth_test =
-               sp->depth_stencil->depth.enabled &&
-               sp->framebuffer.zsbuf &&
-               !sp->depth_stencil->alpha.enabled &&
-               !sp->fs->info.uses_kill &&
-               !sp->fs->info.writes_z;
+      sp->depth_stencil->depth.enabled &&
+      sp->framebuffer.zsbuf &&
+      !sp->depth_stencil->alpha.enabled &&
+      !sp->fs->info.uses_kill &&
+      !sp->fs->info.writes_z;
 
    /* build up the pipeline in reverse order... */
-      sp->quad.first = sp->quad.output;
-
-      if (sp->blend->colormask != 0xf) {
-         sp_push_quad_first( sp, sp->quad.colormask );
-      }
-
-      if (sp->blend->blend_enable ||
-          sp->blend->logicop_enable) {
-         sp_push_quad_first( sp, sp->quad.blend );
-      }
-
-      if (sp->active_query_count) {
-         sp_push_quad_first( sp, sp->quad.occlusion );
-      }
-
-      if (sp->rasterizer->poly_smooth ||
-          sp->rasterizer->line_smooth ||
-          sp->rasterizer->point_smooth) {
-         sp_push_quad_first( sp, sp->quad.coverage );
-      }
-
-      if (!early_depth_test) {
-         sp_build_depth_stencil( sp );
-      }
-
-      if (sp->depth_stencil->alpha.enabled) {
-         sp_push_quad_first( sp, sp->quad.alpha_test );
-      }
-
-      /* XXX always enable shader? */
-      if (1) {
-         sp_push_quad_first( sp, sp->quad.shade );
-      }
-
-      if (early_depth_test) {
-         sp_build_depth_stencil( sp );
-         sp_push_quad_first( sp, sp->quad.earlyz );
-      }
+
+   /* Color combine
+    */
+   sp->quad.first = sp->quad.output;
+
+   if (sp->blend->colormask != 0xf) {
+      sp_push_quad_first( sp, sp->quad.colormask );
+   }
+
+   if (sp->blend->blend_enable ||
+       sp->blend->logicop_enable) {
+      sp_push_quad_first( sp, sp->quad.blend );
+   }
+
+   if (sp->rasterizer->poly_smooth ||
+       sp->rasterizer->line_smooth ||
+       sp->rasterizer->point_smooth) {
+      sp_push_quad_first( sp, sp->quad.coverage );
+   }
+
+   /* Shade/Depth/Stencil/Alpha
+    */
+   if (sp->active_query_count) {
+      sp_push_quad_first( sp, sp->quad.occlusion );
+   }
+
+   if (!early_depth_test) {
+      sp_build_depth_stencil( sp );
+   }
+
+   if (sp->depth_stencil->alpha.enabled) {
+      sp_push_quad_first( sp, sp->quad.alpha_test );
+   }
+
+   sp_push_quad_first( sp, sp->quad.shade );
+
+   if (early_depth_test) {
+      sp_build_depth_stencil( sp );
+      sp_push_quad_first( sp, sp->quad.earlyz );
+   }
 }
 
index 0e40586ffc8a653afd3d4a62e43ddf826f7f9c8c..add31ba7056599444e496b1bdd8397883d4a7564 100644 (file)
@@ -49,7 +49,7 @@ struct quad_stage {
    void (*begin)(struct quad_stage *qs);
 
    /** the stage action */
-   void (*run)(struct quad_stage *qs, struct quad_header *quad);
+   void (*run)(struct quad_stage *qs, struct quad_header *quad[], unsigned nr);
 
    void (*destroy)(struct quad_stage *qs);
 };
@@ -69,6 +69,6 @@ struct quad_stage *sp_quad_output_stage( struct softpipe_context *softpipe );
 
 void sp_build_quad_pipeline(struct softpipe_context *sp);
 
-void sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
+boolean sp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
 
 #endif /* SP_QUAD_PIPE_H */
index 34a8d9e9f6aa3ae312bd1bca9555326f0752376e..706dd2f756be2ac199cf4113f7b282c766222011 100644 (file)
@@ -198,7 +198,8 @@ apply_stencil_op(ubyte stencilVals[QUAD_SIZE],
  * depth testing.
  */
 static void
-stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
+stencil_test_quad(struct quad_stage *qs, struct quad_header *quads[],
+                  unsigned nr)
 {
    struct softpipe_context *softpipe = qs->softpipe;
    struct pipe_surface *ps = softpipe->framebuffer.zsbuf;
@@ -206,9 +207,12 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
    ubyte ref, wrtMask, valMask;
    ubyte stencilVals[QUAD_SIZE];
    struct softpipe_cached_tile *tile
-      = sp_get_cached_tile(softpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
-   uint j;
-   uint face = quad->input.facing;
+      = sp_get_cached_tile(softpipe->zsbuf_cache, 
+                           quads[0]->input.x0, 
+                           quads[0]->input.y0);
+   uint face = quads[0]->input.facing;
+   uint pass = 0;
+   uint j, q;
 
    if (!softpipe->depth_stencil->stencil[1].enabled) {
       /* single-sided stencil test, use front (face=0) state */
@@ -227,103 +231,110 @@ stencil_test_quad(struct quad_stage *qs, struct quad_header *quad)
 
    assert(ps); /* shouldn't get here if there's no stencil buffer */
 
-   /* get stencil values from cached tile */
-   switch (ps->format) {
-   case PIPE_FORMAT_S8Z24_UNORM:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = quad->input.x0 % TILE_SIZE + (j & 1);
-         int y = quad->input.y0 % TILE_SIZE + (j >> 1);
-         stencilVals[j] = tile->data.depth32[y][x] >> 24;
-      }
-      break;
-   case PIPE_FORMAT_Z24S8_UNORM:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = quad->input.x0 % TILE_SIZE + (j & 1);
-         int y = quad->input.y0 % TILE_SIZE + (j >> 1);
-         stencilVals[j] = tile->data.depth32[y][x] & 0xff;
-      }
-      break;
-   case PIPE_FORMAT_S8_UNORM:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = quad->input.x0 % TILE_SIZE + (j & 1);
-         int y = quad->input.y0 % TILE_SIZE + (j >> 1);
-         stencilVals[j] = tile->data.stencil8[y][x];
+   for (q = 0; q < nr; q++) {
+      struct quad_header *quad = quads[q];
+
+      /* get stencil values from cached tile */
+      switch (ps->format) {
+      case PIPE_FORMAT_S8Z24_UNORM:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->input.x0 % TILE_SIZE + (j & 1);
+            int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+            stencilVals[j] = tile->data.depth32[y][x] >> 24;
+         }
+         break;
+      case PIPE_FORMAT_Z24S8_UNORM:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->input.x0 % TILE_SIZE + (j & 1);
+            int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+            stencilVals[j] = tile->data.depth32[y][x] & 0xff;
+         }
+         break;
+      case PIPE_FORMAT_S8_UNORM:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->input.x0 % TILE_SIZE + (j & 1);
+            int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+            stencilVals[j] = tile->data.stencil8[y][x];
+         }
+         break;
+      default:
+         assert(0);
       }
-      break;
-   default:
-      assert(0);
-   }
 
-   /* do the stencil test first */
-   {
-      unsigned passMask, failMask;
-      passMask = do_stencil_test(stencilVals, func, ref, valMask);
-      failMask = quad->inout.mask & ~passMask;
-      quad->inout.mask &= passMask;
+      /* do the stencil test first */
+      {
+         unsigned passMask, failMask;
+         passMask = do_stencil_test(stencilVals, func, ref, valMask);
+         failMask = quad->inout.mask & ~passMask;
+         quad->inout.mask &= passMask;
 
-      if (failOp != PIPE_STENCIL_OP_KEEP) {
-         apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
+         if (failOp != PIPE_STENCIL_OP_KEEP) {
+            apply_stencil_op(stencilVals, failMask, failOp, ref, wrtMask);
+         }
       }
-   }
 
-   if (quad->inout.mask) {
-      /* now the pixels that passed the stencil test are depth tested */
-      if (softpipe->depth_stencil->depth.enabled) {
-         const unsigned origMask = quad->inout.mask;
+      if (quad->inout.mask) {
+         /* now the pixels that passed the stencil test are depth tested */
+         if (softpipe->depth_stencil->depth.enabled) {
+            const unsigned origMask = quad->inout.mask;
 
-         sp_depth_test_quad(qs, quad);  /* quad->mask is updated */
+            sp_depth_test_quad(qs, quad);  /* quad->mask is updated */
 
-         /* update stencil buffer values according to z pass/fail result */
-         if (zFailOp != PIPE_STENCIL_OP_KEEP) {
-            const unsigned failMask = origMask & ~quad->inout.mask;
-            apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
-         }
+            /* update stencil buffer values according to z pass/fail result */
+            if (zFailOp != PIPE_STENCIL_OP_KEEP) {
+               const unsigned failMask = origMask & ~quad->inout.mask;
+               apply_stencil_op(stencilVals, failMask, zFailOp, ref, wrtMask);
+            }
 
-         if (zPassOp != PIPE_STENCIL_OP_KEEP) {
-            const unsigned passMask = origMask & quad->inout.mask;
-            apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
+            if (zPassOp != PIPE_STENCIL_OP_KEEP) {
+               const unsigned passMask = origMask & quad->inout.mask;
+               apply_stencil_op(stencilVals, passMask, zPassOp, ref, wrtMask);
+            }
+         }
+         else {
+            /* no depth test, apply Zpass operator to stencil buffer values */
+            apply_stencil_op(stencilVals, quad->inout.mask, zPassOp, ref, wrtMask);
          }
-      }
-      else {
-         /* no depth test, apply Zpass operator to stencil buffer values */
-         apply_stencil_op(stencilVals, quad->inout.mask, zPassOp, ref, wrtMask);
-      }
-
-   }
 
-   /* put new stencil values into cached tile */
-   switch (ps->format) {
-   case PIPE_FORMAT_S8Z24_UNORM:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = quad->input.x0 % TILE_SIZE + (j & 1);
-         int y = quad->input.y0 % TILE_SIZE + (j >> 1);
-         uint s8z24 = tile->data.depth32[y][x];
-         s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff);
-         tile->data.depth32[y][x] = s8z24;
       }
-      break;
-   case PIPE_FORMAT_Z24S8_UNORM:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = quad->input.x0 % TILE_SIZE + (j & 1);
-         int y = quad->input.y0 % TILE_SIZE + (j >> 1);
-         uint z24s8 = tile->data.depth32[y][x];
-         z24s8 = (z24s8 & 0xffffff00) | stencilVals[j];
-         tile->data.depth32[y][x] = z24s8;
-      }
-      break;
-   case PIPE_FORMAT_S8_UNORM:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         int x = quad->input.x0 % TILE_SIZE + (j & 1);
-         int y = quad->input.y0 % TILE_SIZE + (j >> 1);
-         tile->data.stencil8[y][x] = stencilVals[j];
+
+      /* put new stencil values into cached tile */
+      switch (ps->format) {
+      case PIPE_FORMAT_S8Z24_UNORM:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->input.x0 % TILE_SIZE + (j & 1);
+            int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+            uint s8z24 = tile->data.depth32[y][x];
+            s8z24 = (stencilVals[j] << 24) | (s8z24 & 0xffffff);
+            tile->data.depth32[y][x] = s8z24;
+         }
+         break;
+      case PIPE_FORMAT_Z24S8_UNORM:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->input.x0 % TILE_SIZE + (j & 1);
+            int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+            uint z24s8 = tile->data.depth32[y][x];
+            z24s8 = (z24s8 & 0xffffff00) | stencilVals[j];
+            tile->data.depth32[y][x] = z24s8;
+         }
+         break;
+      case PIPE_FORMAT_S8_UNORM:
+         for (j = 0; j < QUAD_SIZE; j++) {
+            int x = quad->input.x0 % TILE_SIZE + (j & 1);
+            int y = quad->input.y0 % TILE_SIZE + (j >> 1);
+            tile->data.stencil8[y][x] = stencilVals[j];
+         }
+         break;
+      default:
+         assert(0);
       }
-      break;
-   default:
-      assert(0);
+
+      if (quad->inout.mask)
+         quads[pass++] = q;
    }
 
-   if (quad->inout.mask)
-      qs->next->run(qs->next, quad);
+   if (pass)
+      qs->next->run(qs->next, quads, pass);
 }
 
 
index 07162db7b6e0864dc1b374bf19d3ca2057a6b017..05665d8e263dfcad0990e099b507994132cbcd5e 100644 (file)
  * Apply polygon stipple to quads produced by triangle rasterization
  */
 static void
-stipple_quad(struct quad_stage *qs, struct quad_header *quad)
+stipple_quad(struct quad_stage *qs, struct quad_header *quads[], unsigned nr)
 {
    static const uint bit31 = 1 << 31;
    static const uint bit30 = 1 << 30;
+   unsigned pass = nr;
 
-   if (quad->input.prim == QUAD_PRIM_TRI) {
+   if (quads[0]->input.prim == QUAD_PRIM_TRI) {
       struct softpipe_context *softpipe = qs->softpipe;
-      /* need to invert Y to index into OpenGL's stipple pattern */
-      const int col0 = quad->input.x0 % 32;
-      const int y0 = quad->input.y0;
-      const int y1 = y0 + 1;
-      const uint stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
-      const uint stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
+      unsigned q;
 
-      /* turn off quad mask bits that fail the stipple test */
-      if ((stipple0 & (bit31 >> col0)) == 0)
-         quad->inout.mask &= ~MASK_TOP_LEFT;
+      pass = 0;
 
-      if ((stipple0 & (bit30 >> col0)) == 0)
-         quad->inout.mask &= ~MASK_TOP_RIGHT;
+      for (q = 0; q < nr; q++)  {
+         struct quad_header *quad = quads[q];
 
-      if ((stipple1 & (bit31 >> col0)) == 0)
-         quad->inout.mask &= ~MASK_BOTTOM_LEFT;
+         const int col0 = quad->input.x0 % 32;
+         const int y0 = quad->input.y0;
+         const int y1 = y0 + 1;
+         const uint stipple0 = softpipe->poly_stipple.stipple[y0 % 32];
+         const uint stipple1 = softpipe->poly_stipple.stipple[y1 % 32];
 
-      if ((stipple1 & (bit30 >> col0)) == 0)
-         quad->inout.mask &= ~MASK_BOTTOM_RIGHT;
+         /* turn off quad mask bits that fail the stipple test */
+         if ((stipple0 & (bit31 >> col0)) == 0)
+            quad->inout.mask &= ~MASK_TOP_LEFT;
 
-      if (!quad->inout.mask) {
-         /* all fragments failed stipple test, end of quad pipeline */
-         return;
+         if ((stipple0 & (bit30 >> col0)) == 0)
+            quad->inout.mask &= ~MASK_TOP_RIGHT;
+
+         if ((stipple1 & (bit31 >> col0)) == 0)
+            quad->inout.mask &= ~MASK_BOTTOM_LEFT;
+
+         if ((stipple1 & (bit30 >> col0)) == 0)
+            quad->inout.mask &= ~MASK_BOTTOM_RIGHT;
+
+         if (quad->inout.mask)
+            quads[pass++] = quad;
       }
    }
 
-   qs->next->run(qs->next, quad);
+   qs->next->run(qs->next, quads, pass);
 }
 
 
index eaf84ed9de9acd1fa7cdd5ff32f574f7405f476a..23dcae89c69d5d093f2e343a736188f7c3974a2f 100644 (file)
@@ -172,7 +172,7 @@ clip_emit_quad( struct setup_context *setup, struct quad_header *quad )
    if (quad->inout.mask) {
       struct softpipe_context *sp = setup->softpipe;
 
-      sp->quad.first->run( sp->quad.first, quad );
+      sp->quad.first->run( sp->quad.first, &quad, 1 );
    }
 }
 
@@ -193,7 +193,7 @@ emit_quad( struct setup_context *setup, struct quad_header *quad, uint thread )
    if (mask & 4) setup->numFragsEmitted++;
    if (mask & 8) setup->numFragsEmitted++;
 #endif
-   sp->quad.first->run( sp->quad.first, quad );
+   sp->quad.first->run( sp->quad.first, &quad, 1 );
 #if DEBUG_FRAGS
    mask = quad->inout.mask;
    if (mask & 1) setup->numFragsWritten++;