llvmpipe: move all depth/stencil/alpha pixel processing into one stage
authorKeith Whitwell <keithw@vmware.com>
Mon, 27 Jul 2009 07:17:45 +0000 (08:17 +0100)
committerJosé Fonseca <jfonseca@vmware.com>
Sat, 29 Aug 2009 08:21:19 +0000 (09:21 +0100)
13 files changed:
src/gallium/drivers/llvmpipe/Makefile
src/gallium/drivers/llvmpipe/lp_context.c
src/gallium/drivers/llvmpipe/lp_context.h
src/gallium/drivers/llvmpipe/lp_quad_alpha_test.c [deleted file]
src/gallium/drivers/llvmpipe/lp_quad_coverage.c [deleted file]
src/gallium/drivers/llvmpipe/lp_quad_depth_test.c
src/gallium/drivers/llvmpipe/lp_quad_earlyz.c [deleted file]
src/gallium/drivers/llvmpipe/lp_quad_fs.c
src/gallium/drivers/llvmpipe/lp_quad_occlusion.c [deleted file]
src/gallium/drivers/llvmpipe/lp_quad_pipe.c
src/gallium/drivers/llvmpipe/lp_quad_pipe.h
src/gallium/drivers/llvmpipe/lp_quad_stencil.c [deleted file]
src/gallium/drivers/llvmpipe/lp_state_derived.c

index 64541ec6551cccb01eb9aba6a67bab17334a985b..20a8c44a24d16522f64fa3695110117645e44503 100644 (file)
@@ -19,13 +19,8 @@ C_SOURCES = \
        lp_prim_vbuf.c \
        lp_quad_pipe.c \
        lp_quad_stipple.c \
-       lp_quad_earlyz.c \
        lp_quad_depth_test.c \
-       lp_quad_stencil.c \
        lp_quad_fs.c \
-       lp_quad_alpha_test.c \
-       lp_quad_occlusion.c \
-       lp_quad_coverage.c \
        lp_quad_blend.c \
        lp_screen.c \
         lp_setup.c \
index 4bb63adfec3ac0555608e2171203abef2626971d..7f2c2b6acd51dff7088fda96a838b45b19c82f29 100644 (file)
@@ -88,14 +88,8 @@ static void llvmpipe_destroy( struct pipe_context *pipe )
    if (llvmpipe->draw)
       draw_destroy( llvmpipe->draw );
 
-      llvmpipe->quad.polygon_stipple->destroy( llvmpipe->quad.polygon_stipple );
-      llvmpipe->quad.earlyz->destroy( llvmpipe->quad.earlyz );
       llvmpipe->quad.shade->destroy( llvmpipe->quad.shade );
-      llvmpipe->quad.alpha_test->destroy( llvmpipe->quad.alpha_test );
       llvmpipe->quad.depth_test->destroy( llvmpipe->quad.depth_test );
-      llvmpipe->quad.stencil_test->destroy( llvmpipe->quad.stencil_test );
-      llvmpipe->quad.occlusion->destroy( llvmpipe->quad.occlusion );
-      llvmpipe->quad.coverage->destroy( llvmpipe->quad.coverage );
       llvmpipe->quad.blend->destroy( llvmpipe->quad.blend );
 
    for (i = 0; i < PIPE_MAX_COLOR_BUFS; i++)
@@ -230,14 +224,8 @@ llvmpipe_create( struct pipe_screen *screen )
 
 
    /* setup quad rendering stages */
-      llvmpipe->quad.polygon_stipple = lp_quad_polygon_stipple_stage(llvmpipe);
-      llvmpipe->quad.earlyz = lp_quad_earlyz_stage(llvmpipe);
       llvmpipe->quad.shade = lp_quad_shade_stage(llvmpipe);
-      llvmpipe->quad.alpha_test = lp_quad_alpha_test_stage(llvmpipe);
       llvmpipe->quad.depth_test = lp_quad_depth_test_stage(llvmpipe);
-      llvmpipe->quad.stencil_test = lp_quad_stencil_test_stage(llvmpipe);
-      llvmpipe->quad.occlusion = lp_quad_occlusion_stage(llvmpipe);
-      llvmpipe->quad.coverage = lp_quad_coverage_stage(llvmpipe);
       llvmpipe->quad.blend = lp_quad_blend_stage(llvmpipe);
 
    /* vertex shader samplers */
index e341cd01afdfdaca8937e9d1c60bc9997cf38aa9..036585808dac56e9d6502b5c83d4e165bf5c1166 100644 (file)
@@ -114,14 +114,8 @@ struct llvmpipe_context {
 
    /** Software quad rendering pipeline */
    struct {
-      struct quad_stage *polygon_stipple;
-      struct quad_stage *earlyz;
       struct quad_stage *shade;
-      struct quad_stage *alpha_test;
-      struct quad_stage *stencil_test;
       struct quad_stage *depth_test;
-      struct quad_stage *occlusion;
-      struct quad_stage *coverage;
       struct quad_stage *blend;
 
       struct quad_stage *first; /**< points to one of the above stages */
diff --git a/src/gallium/drivers/llvmpipe/lp_quad_alpha_test.c b/src/gallium/drivers/llvmpipe/lp_quad_alpha_test.c
deleted file mode 100644 (file)
index 947daf5..0000000
+++ /dev/null
@@ -1,112 +0,0 @@
-
-/**
- * quad alpha test
- */
-
-#include "lp_context.h"
-#include "lp_quad.h"
-#include "lp_quad_pipe.h"
-#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->llvmpipe->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 *quads[], 
-                unsigned nr)
-{
-   switch (qs->llvmpipe->depth_stencil->alpha.func) {
-   case PIPE_FUNC_LESS:
-      alpha_test_quads_LESS( qs, quads, nr );
-      break;
-   case PIPE_FUNC_EQUAL:
-      alpha_test_quads_EQUAL( qs, quads, nr );
-      break;
-   case PIPE_FUNC_LEQUAL:
-      alpha_test_quads_LEQUAL( qs, quads, nr );
-      break;
-   case PIPE_FUNC_GREATER:
-      alpha_test_quads_GREATER( qs, quads, nr );
-      break;
-   case PIPE_FUNC_NOTEQUAL:
-      alpha_test_quads_NOTEQUAL( qs, quads, nr );
-      break;
-   case PIPE_FUNC_GEQUAL:
-      alpha_test_quads_GEQUAL( qs, quads, nr );
-      break;
-   case PIPE_FUNC_ALWAYS:
-      assert(0); /* should be caught earlier */
-      qs->next->run(qs->next, quads, nr);
-      break;
-   case PIPE_FUNC_NEVER:
-   default:
-      assert(0); /* should be caught earlier */
-      return;
-   }
-}
-
-
-static void alpha_test_begin(struct quad_stage *qs)
-{
-   qs->next->begin(qs->next);
-}
-
-
-static void alpha_test_destroy(struct quad_stage *qs)
-{
-   FREE( qs );
-}
-
-
-struct quad_stage *
-lp_quad_alpha_test_stage( struct llvmpipe_context *llvmpipe )
-{
-   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
-
-   stage->llvmpipe = llvmpipe;
-   stage->begin = alpha_test_begin;
-   stage->run = alpha_test_quad;
-   stage->destroy = alpha_test_destroy;
-
-   return stage;
-}
diff --git a/src/gallium/drivers/llvmpipe/lp_quad_coverage.c b/src/gallium/drivers/llvmpipe/lp_quad_coverage.c
deleted file mode 100644 (file)
index 9bc31df..0000000
+++ /dev/null
@@ -1,101 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-
-/**
- * \brief  Apply AA coverage to quad alpha valus
- * \author  Brian Paul
- */
-
-
-#include "pipe/p_defines.h"
-#include "util/u_memory.h"
-#include "lp_context.h"
-#include "lp_quad.h"
-#include "lp_quad_pipe.h"
-
-
-/**
- * Multiply quad's alpha values by the fragment coverage.
- */
-static INLINE void
-coverage_quad(struct quad_stage *qs, struct quad_header *quad)
-{
-   struct llvmpipe_context *llvmpipe = qs->llvmpipe;
-   uint cbuf;
-
-   /* loop over colorbuffer outputs */
-   for (cbuf = 0; cbuf < llvmpipe->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)
-{
-   unsigned i;
-
-   for (i = 0; i < nr; i++)
-      coverage_quad( qs, quads[i] );
-
-   qs->next->run(qs->next, quads, nr);
-}
-
-static void coverage_begin(struct quad_stage *qs)
-{
-   qs->next->begin(qs->next);
-}
-
-
-static void coverage_destroy(struct quad_stage *qs)
-{
-   FREE( qs );
-}
-
-
-struct quad_stage *lp_quad_coverage_stage( struct llvmpipe_context *llvmpipe )
-{
-   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
-
-   stage->llvmpipe = llvmpipe;
-   stage->begin = coverage_begin;
-   stage->run = coverage_run;
-   stage->destroy = coverage_destroy;
-
-   return stage;
-}
index 8ecd68393f3128479d1ea52ddbc2fb13fb066753..a550299394d6e8b7a0c425c2d084efefd34f35c6 100644 (file)
 
 #include "pipe/p_defines.h"
 #include "util/u_memory.h"
+#include "tgsi/tgsi_scan.h"
 #include "lp_context.h"
 #include "lp_quad.h"
 #include "lp_surface.h"
 #include "lp_quad_pipe.h"
 #include "lp_tile_cache.h"
+#include "lp_state.h"           /* for lp_fragment_shader */
 
 
-/**
- * Do depth testing for a quad.
- * Not static since it's used by the stencil code.
- */
+struct depth_data {
+   struct pipe_surface *ps;
+   enum pipe_format format;
+   unsigned bzzzz[QUAD_SIZE];  /**< Z values fetched from depth buffer */
+   unsigned qzzzz[QUAD_SIZE];  /**< Z values from the quad */
+   ubyte stencilVals[QUAD_SIZE];
+   struct llvmpipe_cached_tile *tile;
+};
 
-/*
- * To increase efficiency, we should probably have multiple versions
- * of this function that are specifically for Z16, Z32 and FP Z buffers.
- * Try to effectively do that with codegen...
- */
 
-boolean
-lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
+
+static void
+get_depth_stencil_values( struct depth_data *data,
+                          const struct quad_header *quad )
 {
-   struct llvmpipe_context *llvmpipe = qs->llvmpipe;
-   struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
-   const enum pipe_format format = ps->format;
-   unsigned bzzzz[QUAD_SIZE];  /**< Z values fetched from depth buffer */
-   unsigned qzzzz[QUAD_SIZE];  /**< Z values from the quad */
-   unsigned zmask = 0;
    unsigned j;
-   struct llvmpipe_cached_tile *tile
-      = lp_get_cached_tile(llvmpipe->zsbuf_cache, quad->input.x0, quad->input.y0);
+   const struct llvmpipe_cached_tile *tile = data->tile;
+
+   switch (data->format) {
+   case PIPE_FORMAT_Z16_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);
+         data->bzzzz[j] = tile->data.depth16[y][x];
+      }
+      break;
+   case PIPE_FORMAT_Z32_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);
+         data->bzzzz[j] = tile->data.depth32[y][x];
+      }
+      break;
+   case PIPE_FORMAT_X8Z24_UNORM:
+   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);
+         data->bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
+         data->stencilVals[j] = tile->data.depth32[y][x] >> 24;
+      }
+   break;
+   case PIPE_FORMAT_Z24X8_UNORM:
+   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);
+         data->bzzzz[j] = tile->data.depth32[y][x] >> 8;
+         data->stencilVals[j] = tile->data.depth32[y][x] & 0xff;
+      }
+      break;
+   default:
+      assert(0);
+   }
+}
 
-   assert(ps); /* shouldn't get here if there's no zbuffer */
+/* If the shader has not been run, interpolate the depth values
+ * ourselves.
+ */
+static void
+interpolate_quad_depth( struct quad_header *quad )
+{
+   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;
+
+   quad->output.depth[0] = z0;
+   quad->output.depth[1] = z0 + dzdx;
+   quad->output.depth[2] = z0 + dzdy;
+   quad->output.depth[3] = z0 + dzdx + dzdy;
+}
 
-   /*
-    * Convert quad's float depth values to int depth values (qzzzz).
+
+static void
+convert_quad_depth( struct depth_data *data, 
+                    const struct quad_header *quad )
+{
+   unsigned j;
+
+   /* Convert quad's float depth values to int depth values (qzzzz).
     * If the Z buffer stores integer values, we _have_ to do the depth
     * compares with integers (not floats).  Otherwise, the float->int->float
     * conversion of Z values (which isn't an identity function) will cause
     * Z-fighting errors.
-    *
-    * Also, get the zbuffer values (bzzzz) from the cached tile.
     */
-   switch (format) {
+   switch (data->format) {
    case PIPE_FORMAT_Z16_UNORM:
       {
          float scale = 65535.0;
 
          for (j = 0; j < QUAD_SIZE; j++) {
-            qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
-         }
-
-         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);
-            bzzzz[j] = tile->data.depth16[y][x];
+            data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
          }
       }
       break;
@@ -94,47 +142,247 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
          double scale = (double) (uint) ~0UL;
 
          for (j = 0; j < QUAD_SIZE; j++) {
-            qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
-         }
-
-         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);
-            bzzzz[j] = tile->data.depth32[y][x];
+            data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
          }
       }
       break;
    case PIPE_FORMAT_X8Z24_UNORM:
-      /* fall-through */
    case PIPE_FORMAT_S8Z24_UNORM:
       {
          float scale = (float) ((1 << 24) - 1);
 
          for (j = 0; j < QUAD_SIZE; j++) {
-            qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
-         }
-
-         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);
-            bzzzz[j] = tile->data.depth32[y][x] & 0xffffff;
+            data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
          }
       }
       break;
    case PIPE_FORMAT_Z24X8_UNORM:
-      /* fall-through */
    case PIPE_FORMAT_Z24S8_UNORM:
       {
          float scale = (float) ((1 << 24) - 1);
 
          for (j = 0; j < QUAD_SIZE; j++) {
-            qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
+            data->qzzzz[j] = (unsigned) (quad->output.depth[j] * scale);
          }
+      }
+      break;
+   default:
+      assert(0);
+   }
+}
 
-         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);
-            bzzzz[j] = tile->data.depth32[y][x] >> 8;
+
+
+static void
+write_depth_stencil_values( struct depth_data *data,
+                            struct quad_header *quad )
+{
+   struct llvmpipe_cached_tile *tile = data->tile;
+   unsigned j;
+
+   /* put updated Z values back into cached tile */
+   switch (data->format) {
+   case PIPE_FORMAT_Z16_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.depth16[y][x] = (ushort) data->bzzzz[j];
+      }
+      break;
+   case PIPE_FORMAT_X8Z24_UNORM:
+   case PIPE_FORMAT_Z32_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.depth32[y][x] = data->bzzzz[j];
+      }
+      break;
+   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);
+         tile->data.depth32[y][x] = (data->stencilVals[j] << 24) | data->bzzzz[j];
+      }
+      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);
+         tile->data.depth32[y][x] = (data->bzzzz[j] << 8) | data->stencilVals[j];
+      }
+      break;
+   case PIPE_FORMAT_Z24X8_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.depth32[y][x] = data->bzzzz[j] << 8;
+      }
+      break;
+   default:
+      assert(0);
+   }
+}
+
+
+
+
+/** Only 8-bit stencil supported */
+#define STENCIL_MAX 0xff
+
+
+/**
+ * Do the basic stencil test (compare stencil buffer values against the
+ * reference value.
+ *
+ * \param data->stencilVals  the stencil values from the stencil buffer
+ * \param func  the stencil func (PIPE_FUNC_x)
+ * \param ref  the stencil reference value
+ * \param valMask  the stencil value mask indicating which bits of the stencil
+ *                 values and ref value are to be used.
+ * \return mask indicating which pixels passed the stencil test
+ */
+static unsigned
+do_stencil_test(struct depth_data *data,
+                unsigned func,
+                unsigned ref, unsigned valMask)
+{
+   unsigned passMask = 0x0;
+   unsigned j;
+
+   ref &= valMask;
+
+   switch (func) {
+   case PIPE_FUNC_NEVER:
+      /* passMask = 0x0 */
+      break;
+   case PIPE_FUNC_LESS:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (ref < (data->stencilVals[j] & valMask)) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_EQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (ref == (data->stencilVals[j] & valMask)) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_LEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (ref <= (data->stencilVals[j] & valMask)) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_GREATER:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (ref > (data->stencilVals[j] & valMask)) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_NOTEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (ref != (data->stencilVals[j] & valMask)) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_GEQUAL:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (ref >= (data->stencilVals[j] & valMask)) {
+            passMask |= (1 << j);
+         }
+      }
+      break;
+   case PIPE_FUNC_ALWAYS:
+      passMask = MASK_ALL;
+      break;
+   default:
+      assert(0);
+   }
+
+   return passMask;
+}
+
+
+/**
+ * Apply the stencil operator to stencil values.
+ *
+ * \param data->stencilVals  the stencil buffer values (read and written)
+ * \param mask  indicates which pixels to update
+ * \param op  the stencil operator (PIPE_STENCIL_OP_x)
+ * \param ref  the stencil reference value
+ * \param wrtMask  writemask controlling which bits are changed in the
+ *                 stencil values
+ */
+static void
+apply_stencil_op(struct depth_data *data,
+                 unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
+{
+   unsigned j;
+   ubyte newstencil[QUAD_SIZE];
+
+   for (j = 0; j < QUAD_SIZE; j++) {
+      newstencil[j] = data->stencilVals[j];
+   }
+
+   switch (op) {
+   case PIPE_STENCIL_OP_KEEP:
+      /* no-op */
+      break;
+   case PIPE_STENCIL_OP_ZERO:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = 0;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_REPLACE:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = ref;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_INCR:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            if (data->stencilVals[j] < STENCIL_MAX) {
+               newstencil[j] = data->stencilVals[j] + 1;
+            }
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_DECR:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            if (data->stencilVals[j] > 0) {
+               newstencil[j] = data->stencilVals[j] - 1;
+            }
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_INCR_WRAP:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = data->stencilVals[j] + 1;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_DECR_WRAP:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = data->stencilVals[j] - 1;
+         }
+      }
+      break;
+   case PIPE_STENCIL_OP_INVERT:
+      for (j = 0; j < QUAD_SIZE; j++) {
+         if (mask & (1 << j)) {
+            newstencil[j] = ~data->stencilVals[j];
          }
       }
       break;
@@ -142,6 +390,39 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
       assert(0);
    }
 
+   /*
+    * update the stencil values
+    */
+   if (wrtMask != STENCIL_MAX) {
+      /* apply bit-wise stencil buffer writemask */
+      for (j = 0; j < QUAD_SIZE; j++) {
+         data->stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & data->stencilVals[j]);
+      }
+   }
+   else {
+      for (j = 0; j < QUAD_SIZE; j++) {
+         data->stencilVals[j] = newstencil[j];
+      }
+   }
+}
+
+   
+
+/*
+ * To increase efficiency, we should probably have multiple versions
+ * of this function that are specifically for Z16, Z32 and FP Z buffers.
+ * Try to effectively do that with codegen...
+ */
+
+static boolean
+depth_test_quad(struct quad_stage *qs, 
+                struct depth_data *data,
+                struct quad_header *quad)
+{
+   struct llvmpipe_context *llvmpipe = qs->llvmpipe;
+   unsigned zmask = 0;
+   unsigned j;
+
    switch (llvmpipe->depth_stencil->depth.func) {
    case PIPE_FUNC_NEVER:
       /* zmask = 0 */
@@ -151,37 +432,37 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
        * Like this:  quad->mask &= (quad->outputs.depth < zzzz);
        */
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (qzzzz[j] < bzzzz[j]) 
+        if (data->qzzzz[j] < data->bzzzz[j]) 
            zmask |= 1 << j;
       }
       break;
    case PIPE_FUNC_EQUAL:
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (qzzzz[j] == bzzzz[j]) 
+        if (data->qzzzz[j] == data->bzzzz[j]) 
            zmask |= 1 << j;
       }
       break;
    case PIPE_FUNC_LEQUAL:
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (qzzzz[j] <= bzzzz[j]) 
+        if (data->qzzzz[j] <= data->bzzzz[j]) 
            zmask |= (1 << j);
       }
       break;
    case PIPE_FUNC_GREATER:
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (qzzzz[j] > bzzzz[j]) 
+        if (data->qzzzz[j] > data->bzzzz[j]) 
            zmask |= (1 << j);
       }
       break;
    case PIPE_FUNC_NOTEQUAL:
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (qzzzz[j] != bzzzz[j]) 
+        if (data->qzzzz[j] != data->bzzzz[j]) 
            zmask |= (1 << j);
       }
       break;
    case PIPE_FUNC_GEQUAL:
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (qzzzz[j] >= bzzzz[j]) 
+        if (data->qzzzz[j] >= data->bzzzz[j]) 
            zmask |= (1 << j);
       }
       break;
@@ -196,83 +477,231 @@ lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
    if (quad->inout.mask == 0)
       return FALSE;
 
+   /* Update our internal copy only if writemask set.  Even if
+    * depth.writemask is FALSE, may still need to write out buffer
+    * data due to stencil changes.
+    */
    if (llvmpipe->depth_stencil->depth.writemask) {
-      
-      /* This is also efficient with sse / spe instructions: 
-       */
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (quad->inout.mask & (1 << j)) {
-           bzzzz[j] = qzzzz[j];
-        }
+         if (quad->inout.mask & (1 << j)) {
+            data->bzzzz[j] = data->qzzzz[j];
+         }
       }
+   }
 
-      /* put updated Z values back into cached tile */
-      switch (format) {
-      case PIPE_FORMAT_Z16_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.depth16[y][x] = (ushort) bzzzz[j];
-         }
-         break;
-      case PIPE_FORMAT_X8Z24_UNORM:
-         /* fall-through */
-         /* (yes, this falls through to a different case than above) */
-      case PIPE_FORMAT_Z32_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.depth32[y][x] = bzzzz[j];
-         }
-         break;
-      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 = (s8z24 & 0xff000000) | bzzzz[j];
-            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 & 0xff) | (bzzzz[j] << 8);
-            tile->data.depth32[y][x] = z24s8;
+   return TRUE;
+}
+
+
+
+/**
+ * Do stencil (and depth) testing.  Stenciling depends on the outcome of
+ * depth testing.
+ */
+static boolean
+depth_stencil_test_quad(struct quad_stage *qs, 
+                        struct depth_data *data,
+                        struct quad_header *quad)
+{
+   struct llvmpipe_context *llvmpipe = qs->llvmpipe;
+   unsigned func, zFailOp, zPassOp, failOp;
+   ubyte ref, wrtMask, valMask;
+   uint face = quad->input.facing;
+
+   if (!llvmpipe->depth_stencil->stencil[1].enabled) {
+      /* single-sided stencil test, use front (face=0) state */
+      face = 0;
+   }
+
+   /* choose front or back face function, operator, etc */
+   /* XXX we could do these initializations once per primitive */
+   func    = llvmpipe->depth_stencil->stencil[face].func;
+   failOp  = llvmpipe->depth_stencil->stencil[face].fail_op;
+   zFailOp = llvmpipe->depth_stencil->stencil[face].zfail_op;
+   zPassOp = llvmpipe->depth_stencil->stencil[face].zpass_op;
+   ref     = llvmpipe->depth_stencil->stencil[face].ref_value;
+   wrtMask = llvmpipe->depth_stencil->stencil[face].writemask;
+   valMask = llvmpipe->depth_stencil->stencil[face].valuemask;
+
+
+   /* do the stencil test first */
+   {
+      unsigned passMask, failMask;
+      passMask = do_stencil_test(data, func, ref, valMask);
+      failMask = quad->inout.mask & ~passMask;
+      quad->inout.mask &= passMask;
+
+      if (failOp != PIPE_STENCIL_OP_KEEP) {
+         apply_stencil_op(data, failMask, failOp, ref, wrtMask);
+      }
+   }
+
+   if (quad->inout.mask) {
+      /* now the pixels that passed the stencil test are depth tested */
+      if (llvmpipe->depth_stencil->depth.enabled) {
+         const unsigned origMask = quad->inout.mask;
+
+         depth_test_quad(qs, data, 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(data, failMask, zFailOp, ref, wrtMask);
          }
-         break;
-      case PIPE_FORMAT_Z24X8_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.depth32[y][x] = bzzzz[j] << 8;
+
+         if (zPassOp != PIPE_STENCIL_OP_KEEP) {
+            const unsigned passMask = origMask & quad->inout.mask;
+            apply_stencil_op(data, passMask, zPassOp, ref, wrtMask);
          }
-         break;
-      default:
-         assert(0);
+      }
+      else {
+         /* no depth test, apply Zpass operator to stencil buffer values */
+         apply_stencil_op(data, quad->inout.mask, zPassOp, ref, wrtMask);
       }
    }
 
-   return TRUE;
+   return quad->inout.mask != 0;
 }
 
 
+#define ALPHATEST( FUNC, COMP )                                         \
+   static int                                                          \
+   alpha_test_quads_##FUNC( struct quad_stage *qs,                      \
+                           struct quad_header *quads[],                 \
+                           unsigned nr )                                \
+   {                                                                    \
+      const float ref = qs->llvmpipe->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];                                \
+      }                                                                 \
+                                                                        \
+      return pass_nr;                                                   \
+   }
+
+
+ALPHATEST( LESS,     < )
+ALPHATEST( EQUAL,    == )
+ALPHATEST( LEQUAL,   <= )
+ALPHATEST( GREATER,  > )
+ALPHATEST( NOTEQUAL, != )
+ALPHATEST( GEQUAL,   >= )
+
+
+/* XXX: Incorporate into shader using KILP.
+ */
+static int
+alpha_test_quads(struct quad_stage *qs, 
+                 struct quad_header *quads[], 
+                 unsigned nr)
+{
+   switch (qs->llvmpipe->depth_stencil->alpha.func) {
+   case PIPE_FUNC_LESS:
+      return alpha_test_quads_LESS( qs, quads, nr );
+   case PIPE_FUNC_EQUAL:
+      return alpha_test_quads_EQUAL( qs, quads, nr );
+      break;
+   case PIPE_FUNC_LEQUAL:
+      return alpha_test_quads_LEQUAL( qs, quads, nr );
+   case PIPE_FUNC_GREATER:
+      return alpha_test_quads_GREATER( qs, quads, nr );
+   case PIPE_FUNC_NOTEQUAL:
+      return alpha_test_quads_NOTEQUAL( qs, quads, nr );
+   case PIPE_FUNC_GEQUAL:
+      return alpha_test_quads_GEQUAL( qs, quads, nr );
+   case PIPE_FUNC_ALWAYS:
+      return nr;
+   case PIPE_FUNC_NEVER:
+   default:
+      return 0;
+   }
+}
+
+static unsigned mask_count[0x8] = 
+{
+   0,                           /* 0x0 */
+   1,                           /* 0x1 */
+   1,                           /* 0x2 */
+   2,                           /* 0x3 */
+   1,                           /* 0x4 */
+   2,                           /* 0x5 */
+   2,                           /* 0x6 */
+   3,                           /* 0x7 */
+};
+
+
+
 static void
 depth_test_quads(struct quad_stage *qs, 
                  struct quad_header *quads[],
                  unsigned nr)
 {
    unsigned i, pass = 0;
+   const struct lp_fragment_shader *fs = qs->llvmpipe->fs;
+   boolean interp_depth = !fs->info.writes_z;
+   struct depth_data data;
 
-   for (i = 0; i < nr; i++) {
-      if (lp_depth_test_quad(qs, quads[i]))
+
+   if (qs->llvmpipe->depth_stencil->alpha.enabled) {
+      nr = alpha_test_quads(qs, quads, nr);
+   }
+
+   if (qs->llvmpipe->framebuffer.zsbuf && 
+       (qs->llvmpipe->depth_stencil->depth.enabled ||
+        qs->llvmpipe->depth_stencil->stencil[0].enabled)) {
+
+      data.ps = qs->llvmpipe->framebuffer.zsbuf;
+      data.format = data.ps->format;
+      data.tile = lp_get_cached_tile(qs->llvmpipe->zsbuf_cache, 
+                                     quads[0]->input.x0, 
+                                     quads[0]->input.y0);
+
+      for (i = 0; i < nr; i++) {
+         get_depth_stencil_values(&data, quads[i]);
+
+         if (qs->llvmpipe->depth_stencil->depth.enabled) {
+            if (interp_depth)
+               interpolate_quad_depth(quads[i]);
+
+            convert_quad_depth(&data, quads[i]);
+         }
+
+         if (qs->llvmpipe->depth_stencil->stencil[0].enabled) {
+            if (!depth_stencil_test_quad(qs, &data, quads[i]))
+               continue;
+         }
+         else {
+            if (!depth_test_quad(qs, &data, quads[i]))
+               continue;
+         }
+
+         if (qs->llvmpipe->depth_stencil->stencil[0].enabled ||
+             qs->llvmpipe->depth_stencil->depth.writemask)
+            write_depth_stencil_values(&data, quads[i]);
+
+         qs->llvmpipe->occlusion_count += mask_count[quads[i]->inout.mask];
          quads[pass++] = quads[i];
+      }
+
+      nr = pass;
    }
-   
-   if (pass)
-      qs->next->run(qs->next, quads, pass);
+
+   if (nr)
+      qs->next->run(qs->next, quads, nr);
 }
 
 
diff --git a/src/gallium/drivers/llvmpipe/lp_quad_earlyz.c b/src/gallium/drivers/llvmpipe/lp_quad_earlyz.c
deleted file mode 100644 (file)
index 915d2d9..0000000
+++ /dev/null
@@ -1,94 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-/**
- * \brief  Quad early-z testing
- */
-
-#include "pipe/p_defines.h"
-#include "util/u_memory.h"
-#include "lp_quad.h"
-#include "lp_quad_pipe.h"
-
-
-/**
- * All this stage does is compute the quad's Z values (which is normally
- * done by the shading stage).
- * The next stage will do the actual depth test.
- */
-static void
-earlyz_quad(
-   struct quad_stage    *qs,
-   struct quad_header   *quads[],
-   unsigned nr )
-{
-   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;
-
-   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;
-
-      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
-earlyz_begin(
-   struct quad_stage *qs )
-{
-   qs->next->begin( qs->next );
-}
-
-static void
-earlyz_destroy(
-   struct quad_stage *qs )
-{
-   FREE( qs );
-}
-
-struct quad_stage *
-lp_quad_earlyz_stage(
-   struct llvmpipe_context *llvmpipe )
-{
-   struct quad_stage *stage = CALLOC_STRUCT( quad_stage );
-
-   stage->llvmpipe = llvmpipe;
-   stage->begin = earlyz_begin;
-   stage->run = earlyz_quad;
-   stage->destroy = earlyz_destroy;
-
-   return stage;
-}
index 25518c09f4070b1bda1b1f9c30b73613f4a47ba7..1da50e493b5535d524055da59cbdf663f0736b13 100644 (file)
@@ -111,24 +111,31 @@ shade_quad(struct quad_stage *qs, struct quad_header *quad)
       }
    }
 
-   if (!z_written) {
-      /* compute Z values now, as in the quad earlyz stage */
-      /* XXX we should really only do this if the earlyz stage is not used */
-      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;
-
-      quad->output.depth[0] = z0;
-      quad->output.depth[1] = z0 + dzdx;
-      quad->output.depth[2] = z0 + dzdy;
-      quad->output.depth[3] = z0 + dzdx + dzdy;
-   }
-
    return TRUE;
 }
 
+
+
+static void
+coverage_quad(struct quad_stage *qs, struct quad_header *quad)
+{
+   struct llvmpipe_context *llvmpipe = qs->llvmpipe;
+   uint cbuf;
+
+   /* loop over colorbuffer outputs */
+   for (cbuf = 0; cbuf < llvmpipe->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];
+      }
+   }
+}
+
+
+
 static void
 shade_quads(struct quad_stage *qs, 
                  struct quad_header *quads[],
@@ -144,8 +151,13 @@ shade_quads(struct quad_stage *qs,
    machine->InterpCoefs = quads[0]->coef;
 
    for (i = 0; i < nr; i++) {
-      if (shade_quad(qs, quads[i]))
-         quads[pass++] = quads[i];
+      if (!shade_quad(qs, quads[i]))
+         continue;
+
+      if (/*do_coverage*/ 0)
+         coverage_quad( qs, quads[i] );
+
+      quads[pass++] = quads[i];
    }
    
    if (pass)
diff --git a/src/gallium/drivers/llvmpipe/lp_quad_occlusion.c b/src/gallium/drivers/llvmpipe/lp_quad_occlusion.c
deleted file mode 100644 (file)
index c4d5b86..0000000
+++ /dev/null
@@ -1,87 +0,0 @@
-/**************************************************************************
- * 
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
- * All Rights Reserved.
- * 
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- * 
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- * 
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- * 
- **************************************************************************/
-
-
-/**
- * \brief  Quad occlusion counter stage
- * \author  Brian Paul
- */
-
-
-#include "pipe/p_defines.h"
-#include "util/u_memory.h"
-#include "lp_context.h"
-#include "lp_quad.h"
-#include "lp_surface.h"
-#include "lp_quad_pipe.h"
-
-static unsigned count_bits( unsigned val )
-{
-   unsigned i;
-
-   for (i = 0; val ; val >>= 1)
-      i += (val & 1);
-
-   return i;
-}
-
-static void
-occlusion_count_quads(struct quad_stage *qs, struct quad_header *quads[], unsigned nr)
-{
-   struct llvmpipe_context *llvmpipe = qs->llvmpipe;
-   unsigned i;
-
-   for (i = 0; i < nr; i++)
-      llvmpipe->occlusion_count += count_bits(quads[i]->inout.mask);
-
-   qs->next->run(qs->next, quads, nr);
-}
-
-
-static void occlusion_begin(struct quad_stage *qs)
-{
-   qs->next->begin(qs->next);
-}
-
-
-static void occlusion_destroy(struct quad_stage *qs)
-{
-   FREE( qs );
-}
-
-
-struct quad_stage *lp_quad_occlusion_stage( struct llvmpipe_context *llvmpipe )
-{
-   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
-
-   stage->llvmpipe = llvmpipe;
-   stage->begin = occlusion_begin;
-   stage->run = occlusion_count_quads;
-   stage->destroy = occlusion_destroy;
-
-   return stage;
-}
index e912f76b347cf83cbea236636b7dd4a20542f62d..5371e1c5773bb2dbf75ea19418f224b88bd69022 100644 (file)
@@ -38,18 +38,6 @@ lp_push_quad_first( struct llvmpipe_context *lp,
    lp->quad.first = quad;
 }
 
-static void
-lp_build_depth_stencil( struct llvmpipe_context *lp )
-{
-   if (lp->depth_stencil->stencil[0].enabled ||
-       lp->depth_stencil->stencil[1].enabled) {
-      lp_push_quad_first( lp, lp->quad.stencil_test );
-   }
-   else if (lp->depth_stencil->depth.enabled &&
-            lp->framebuffer.zsbuf) {
-      lp_push_quad_first( lp, lp->quad.depth_test );
-   }
-}
 
 void
 lp_build_quad_pipeline(struct llvmpipe_context *lp)
@@ -61,37 +49,15 @@ lp_build_quad_pipeline(struct llvmpipe_context *lp)
       !lp->fs->info.uses_kill &&
       !lp->fs->info.writes_z;
 
-   /* build up the pipeline in reverse order... */
-
-   /* Color combine
-    */
    lp->quad.first = lp->quad.blend;
 
-   /* Shade/Depth/Stencil/Alpha
-    */
-   if ((lp->rasterizer->poly_smooth && lp->reduced_prim == PIPE_PRIM_TRIANGLES) ||
-       (lp->rasterizer->line_smooth && lp->reduced_prim == PIPE_PRIM_LINES) ||
-       (lp->rasterizer->point_smooth && lp->reduced_prim == PIPE_PRIM_POINTS)) {
-      lp_push_quad_first( lp, lp->quad.coverage );
-   }
-
-   if (lp->active_query_count) {
-      lp_push_quad_first( lp, lp->quad.occlusion );
-   }
-
-   if (!early_depth_test) {
-      lp_build_depth_stencil( lp );
-   }
-
-   if (lp->depth_stencil->alpha.enabled) {
-      lp_push_quad_first( lp, lp->quad.alpha_test );
-   }
-
-   lp_push_quad_first( lp, lp->quad.shade );
-
    if (early_depth_test) {
-      lp_build_depth_stencil( lp );
-      lp_push_quad_first( lp, lp->quad.earlyz );
+      lp_push_quad_first( lp, lp->quad.shade );
+      lp_push_quad_first( lp, lp->quad.depth_test );
+   }
+   else {
+      lp_push_quad_first( lp, lp->quad.depth_test );
+      lp_push_quad_first( lp, lp->quad.shade );
    }
 }
 
index 5c8c7b3a7371434283dcdfc59de99a36ce15c457..ee0dd65dd5c6695ee7d86cd2b8d3bd962d2b4f68 100644 (file)
@@ -69,6 +69,4 @@ struct quad_stage *lp_quad_output_stage( struct llvmpipe_context *llvmpipe );
 
 void lp_build_quad_pipeline(struct llvmpipe_context *lp);
 
-boolean lp_depth_test_quad(struct quad_stage *qs, struct quad_header *quad);
-
 #endif /* LP_QUAD_PIPE_H */
diff --git a/src/gallium/drivers/llvmpipe/lp_quad_stencil.c b/src/gallium/drivers/llvmpipe/lp_quad_stencil.c
deleted file mode 100644 (file)
index 150d6d3..0000000
+++ /dev/null
@@ -1,363 +0,0 @@
-
-/**
- * \brief Quad stencil testing
- */
-
-
-#include "lp_context.h"
-#include "lp_quad.h"
-#include "lp_surface.h"
-#include "lp_tile_cache.h"
-#include "lp_quad_pipe.h"
-#include "pipe/p_defines.h"
-#include "util/u_memory.h"
-
-
-/** Only 8-bit stencil supported */
-#define STENCIL_MAX 0xff
-
-
-/**
- * Do the basic stencil test (compare stencil buffer values against the
- * reference value.
- *
- * \param stencilVals  the stencil values from the stencil buffer
- * \param func  the stencil func (PIPE_FUNC_x)
- * \param ref  the stencil reference value
- * \param valMask  the stencil value mask indicating which bits of the stencil
- *                 values and ref value are to be used.
- * \return mask indicating which pixels passed the stencil test
- */
-static unsigned
-do_stencil_test(const ubyte stencilVals[QUAD_SIZE], unsigned func,
-                unsigned ref, unsigned valMask)
-{
-   unsigned passMask = 0x0;
-   unsigned j;
-
-   ref &= valMask;
-
-   switch (func) {
-   case PIPE_FUNC_NEVER:
-      /* passMask = 0x0 */
-      break;
-   case PIPE_FUNC_LESS:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (ref < (stencilVals[j] & valMask)) {
-            passMask |= (1 << j);
-         }
-      }
-      break;
-   case PIPE_FUNC_EQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (ref == (stencilVals[j] & valMask)) {
-            passMask |= (1 << j);
-         }
-      }
-      break;
-   case PIPE_FUNC_LEQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (ref <= (stencilVals[j] & valMask)) {
-            passMask |= (1 << j);
-         }
-      }
-      break;
-   case PIPE_FUNC_GREATER:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (ref > (stencilVals[j] & valMask)) {
-            passMask |= (1 << j);
-         }
-      }
-      break;
-   case PIPE_FUNC_NOTEQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (ref != (stencilVals[j] & valMask)) {
-            passMask |= (1 << j);
-         }
-      }
-      break;
-   case PIPE_FUNC_GEQUAL:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (ref >= (stencilVals[j] & valMask)) {
-            passMask |= (1 << j);
-         }
-      }
-      break;
-   case PIPE_FUNC_ALWAYS:
-      passMask = MASK_ALL;
-      break;
-   default:
-      assert(0);
-   }
-
-   return passMask;
-}
-
-
-/**
- * Apply the stencil operator to stencil values.
- *
- * \param stencilVals  the stencil buffer values (read and written)
- * \param mask  indicates which pixels to update
- * \param op  the stencil operator (PIPE_STENCIL_OP_x)
- * \param ref  the stencil reference value
- * \param wrtMask  writemask controlling which bits are changed in the
- *                 stencil values
- */
-static void
-apply_stencil_op(ubyte stencilVals[QUAD_SIZE],
-                 unsigned mask, unsigned op, ubyte ref, ubyte wrtMask)
-{
-   unsigned j;
-   ubyte newstencil[QUAD_SIZE];
-
-   for (j = 0; j < QUAD_SIZE; j++) {
-      newstencil[j] = stencilVals[j];
-   }
-
-   switch (op) {
-   case PIPE_STENCIL_OP_KEEP:
-      /* no-op */
-      break;
-   case PIPE_STENCIL_OP_ZERO:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (mask & (1 << j)) {
-            newstencil[j] = 0;
-         }
-      }
-      break;
-   case PIPE_STENCIL_OP_REPLACE:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (mask & (1 << j)) {
-            newstencil[j] = ref;
-         }
-      }
-      break;
-   case PIPE_STENCIL_OP_INCR:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (mask & (1 << j)) {
-            if (stencilVals[j] < STENCIL_MAX) {
-               newstencil[j] = stencilVals[j] + 1;
-            }
-         }
-      }
-      break;
-   case PIPE_STENCIL_OP_DECR:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (mask & (1 << j)) {
-            if (stencilVals[j] > 0) {
-               newstencil[j] = stencilVals[j] - 1;
-            }
-         }
-      }
-      break;
-   case PIPE_STENCIL_OP_INCR_WRAP:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (mask & (1 << j)) {
-            newstencil[j] = stencilVals[j] + 1;
-         }
-      }
-      break;
-   case PIPE_STENCIL_OP_DECR_WRAP:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (mask & (1 << j)) {
-            newstencil[j] = stencilVals[j] - 1;
-         }
-      }
-      break;
-   case PIPE_STENCIL_OP_INVERT:
-      for (j = 0; j < QUAD_SIZE; j++) {
-         if (mask & (1 << j)) {
-            newstencil[j] = ~stencilVals[j];
-         }
-      }
-      break;
-   default:
-      assert(0);
-   }
-
-   /*
-    * update the stencil values
-    */
-   if (wrtMask != STENCIL_MAX) {
-      /* apply bit-wise stencil buffer writemask */
-      for (j = 0; j < QUAD_SIZE; j++) {
-         stencilVals[j] = (wrtMask & newstencil[j]) | (~wrtMask & stencilVals[j]);
-      }
-   }
-   else {
-      for (j = 0; j < QUAD_SIZE; j++) {
-         stencilVals[j] = newstencil[j];
-      }
-   }
-}
-
-
-/**
- * Do stencil (and depth) testing.  Stenciling depends on the outcome of
- * depth testing.
- */
-static void
-stencil_test_quad(struct quad_stage *qs, struct quad_header *quads[],
-                  unsigned nr)
-{
-   struct llvmpipe_context *llvmpipe = qs->llvmpipe;
-   struct pipe_surface *ps = llvmpipe->framebuffer.zsbuf;
-   unsigned func, zFailOp, zPassOp, failOp;
-   ubyte ref, wrtMask, valMask;
-   ubyte stencilVals[QUAD_SIZE];
-   struct llvmpipe_cached_tile *tile
-      = lp_get_cached_tile(llvmpipe->zsbuf_cache, 
-                           quads[0]->input.x0, 
-                           quads[0]->input.y0);
-   uint face = quads[0]->input.facing;
-   uint pass = 0;
-   uint j, q;
-
-   if (!llvmpipe->depth_stencil->stencil[1].enabled) {
-      /* single-sided stencil test, use front (face=0) state */
-      face = 0;
-   }
-
-   /* choose front or back face function, operator, etc */
-   /* XXX we could do these initializations once per primitive */
-   func    = llvmpipe->depth_stencil->stencil[face].func;
-   failOp  = llvmpipe->depth_stencil->stencil[face].fail_op;
-   zFailOp = llvmpipe->depth_stencil->stencil[face].zfail_op;
-   zPassOp = llvmpipe->depth_stencil->stencil[face].zpass_op;
-   ref     = llvmpipe->depth_stencil->stencil[face].ref_value;
-   wrtMask = llvmpipe->depth_stencil->stencil[face].writemask;
-   valMask = llvmpipe->depth_stencil->stencil[face].valuemask;
-
-   assert(ps); /* shouldn't get here if there's no stencil buffer */
-
-   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);
-      }
-
-      /* 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 (quad->inout.mask) {
-         /* now the pixels that passed the stencil test are depth tested */
-         if (llvmpipe->depth_stencil->depth.enabled) {
-            const unsigned origMask = quad->inout.mask;
-
-            lp_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);
-            }
-
-            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);
-         }
-
-      }
-
-      /* 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);
-      }
-
-      if (quad->inout.mask)
-         quads[pass++] = quad;
-   }
-
-   if (pass)
-      qs->next->run(qs->next, quads, pass);
-}
-
-
-static void stencil_begin(struct quad_stage *qs)
-{
-   qs->next->begin(qs->next);
-}
-
-
-static void stencil_destroy(struct quad_stage *qs)
-{
-   FREE( qs );
-}
-
-
-struct quad_stage *lp_quad_stencil_test_stage( struct llvmpipe_context *llvmpipe )
-{
-   struct quad_stage *stage = CALLOC_STRUCT(quad_stage);
-
-   stage->llvmpipe = llvmpipe;
-   stage->begin = stencil_begin;
-   stage->run = stencil_test_quad;
-   stage->destroy = stencil_destroy;
-
-   return stage;
-}
index e2b6b8e6027152d4daf447183540fd1bef82ee0b..a2bf27cc6715aac31d4e12e065bc74819f8b9285 100644 (file)
@@ -246,9 +246,7 @@ void llvmpipe_update_derived( struct llvmpipe_context *llvmpipe )
    if (llvmpipe->dirty & (LP_NEW_BLEND |
                           LP_NEW_DEPTH_STENCIL_ALPHA |
                           LP_NEW_FRAMEBUFFER |
-                          LP_NEW_RASTERIZER |
-                          LP_NEW_FS | 
-                         LP_NEW_QUERY))
+                          LP_NEW_FS))
       lp_build_quad_pipeline(llvmpipe);
 
    llvmpipe->dirty = 0;