template code for span functions for flat, memory-based frame buffers
[mesa.git] / src / mesa / swrast / s_alpha.c
index 7ee0f1b118f3af04141ae1ba44cb05e697c5f8e0..5cbfe8617a58bedfafb42bb465ee8d5d3f817e0d 100644 (file)
@@ -1,4 +1,4 @@
-/* $Id: s_alpha.c,v 1.7 2002/01/28 00:07:33 brianp Exp $ */
+/* $Id: s_alpha.c,v 1.12 2002/10/04 19:10:12 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  */
 
+/**
+ * \file swrast/s_alpha.c
+ * \brief Functions to apply alpha test.
+ */
 
 #include "glheader.h"
 #include "context.h"
 #include "mmath.h"
 
 #include "s_alpha.h"
+#include "s_context.h"
 
 
-/*
- * Apply the alpha test to a span of pixels.
- * In:  rgba - array of pixels
- * In/Out:  span -
- * Return:  0 = all pixels in the span failed the alpha test.
- *          1 = one or more pixels passed the alpha test.
+/**
+ * \fn GLint _mesa_alpha_test( const GLcontext *ctx, struct sw_span *span )
+ * \brief Apply the alpha test to a span of pixels.
+ * \return
+ *      - "0" = all pixels in the span failed the alpha test.
+ *      - "1" = one or more pixels passed the alpha test.
  */
 GLint
-_mesa_alpha_test( const GLcontext *ctx, struct sw_span *span,
-                  CONST GLchan rgba[][4])
+_mesa_alpha_test( const GLcontext *ctx, struct sw_span *span )
 {
+   const GLchan (*rgba)[4] = (const GLchan (*)[4]) span->array->rgba;
+   GLchan ref;
+   const GLuint n = span->end;
+   GLubyte *mask = span->array->mask;
    GLuint i;
-   const GLchan ref = ctx->Color.AlphaRef;
-   GLubyte *mask = span->mask;
 
-   ASSERT(span->arrayMask & SPAN_RGBA);
+   CLAMPED_FLOAT_TO_CHAN(ref, ctx->Color.AlphaRef);
 
-   /* switch cases ordered from most frequent to less frequent */
-   switch (ctx->Color.AlphaFunc) {
-      case GL_LESS:
-         for (i=span->start; i<span->end; i++) {
-           mask[i] &= (rgba[i][ACOMP] < ref);
-        }
-        break;
-      case GL_LEQUAL:
-         for (i=span->start; i<span->end; i++)
-           mask[i] &= (rgba[i][ACOMP] <= ref);
-        break;
-      case GL_GEQUAL:
-         for (i=span->start; i<span->end; i++) {
-           mask[i] &= (rgba[i][ACOMP] >= ref);
-        }
-        break;
-      case GL_GREATER:
-         for (i=span->start; i<span->end; i++) {
-           mask[i] &= (rgba[i][ACOMP] > ref);
-        }
-        break;
-      case GL_NOTEQUAL:
-         for (i=span->start; i<span->end; i++) {
-           mask[i] &= (rgba[i][ACOMP] != ref);
-        }
-        break;
-      case GL_EQUAL:
-         for (i=span->start; i<span->end; i++) {
-           mask[i] &= (rgba[i][ACOMP] == ref);
-        }
-        break;
-      case GL_ALWAYS:
-        /* do nothing */
-        return 1;
-      case GL_NEVER:
-         /* caller should check for zero! */
-        return 0;
-      default:
-        _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
-         return 0;
+   if (span->arrayMask & SPAN_RGBA) {
+      /* Use the array values */
+      switch (ctx->Color.AlphaFunc) {
+         case GL_LESS:
+            for (i = 0; i < n; i++)
+               mask[i] &= (rgba[i][ACOMP] < ref);
+            break;
+         case GL_LEQUAL:
+            for (i = 0; i < n; i++)
+               mask[i] &= (rgba[i][ACOMP] <= ref);
+            break;
+         case GL_GEQUAL:
+            for (i = 0; i < n; i++)
+               mask[i] &= (rgba[i][ACOMP] >= ref);
+            break;
+         case GL_GREATER:
+            for (i = 0; i < n; i++)
+               mask[i] &= (rgba[i][ACOMP] > ref);
+            break;
+         case GL_NOTEQUAL:
+            for (i = 0; i < n; i++)
+               mask[i] &= (rgba[i][ACOMP] != ref);
+            break;
+         case GL_EQUAL:
+            for (i = 0; i < n; i++)
+               mask[i] &= (rgba[i][ACOMP] == ref);
+            break;
+         case GL_ALWAYS:
+            /* do nothing */
+            return 1;
+         case GL_NEVER:
+            /* caller should check for zero! */
+            span->writeAll = GL_FALSE;
+            return 0;
+         default:
+            _mesa_problem( ctx, "Invalid alpha test in _mesa_alpha_test" );
+            return 0;
+      }
+   }
+   else {
+      /* Use the interpolation values */
+#if CHAN_TYPE == GL_FLOAT
+      const GLfloat alphaStep = span->alphaStep;
+      GLfloat alpha = span->alpha;
+      ASSERT(span->interpMask & SPAN_RGBA);
+      switch (ctx->Color.AlphaFunc) {
+         case GL_LESS:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (alpha < ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_LEQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (alpha <= ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_GEQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (alpha >= ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_GREATER:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (alpha > ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_NOTEQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (alpha != ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_EQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (alpha == ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_ALWAYS:
+            /* do nothing */
+            return 1;
+         case GL_NEVER:
+            /* caller should check for zero! */
+            span->writeAll = GL_FALSE;
+            return 0;
+         default:
+            _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
+            return 0;
+      }
+#else
+      /* 8 or 16-bit channel interpolation */
+      const GLfixed alphaStep = span->alphaStep;
+      GLfixed alpha = span->alpha;
+      ASSERT(span->interpMask & SPAN_RGBA);
+      switch (ctx->Color.AlphaFunc) {
+         case GL_LESS:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (FixedToChan(alpha) < ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_LEQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (FixedToChan(alpha) <= ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_GEQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (FixedToChan(alpha) >= ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_GREATER:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (FixedToChan(alpha) > ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_NOTEQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (FixedToChan(alpha) != ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_EQUAL:
+            for (i = 0; i < n; i++) {
+               mask[i] &= (FixedToChan(alpha) == ref);
+               alpha += alphaStep;
+            }
+            break;
+         case GL_ALWAYS:
+            /* do nothing */
+            return 1;
+         case GL_NEVER:
+            /* caller should check for zero! */
+            span->writeAll = GL_FALSE;
+            return 0;
+         default:
+            _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
+            return 0;
+      }
+#endif /* CHAN_TYPE */
    }
 
 #if 0
    /* XXXX This causes conformance failures!!!! */
    while ((span->start <= span->end)  &&
-         (mask[span->start] == 0))
+          (mask[span->start] == 0))
      span->start ++;
 
    while ((span->end >= span->start)  &&
-         (mask[span->end] == 0))
+          (mask[span->end] == 0))
      span->end --;
 #endif
+
    span->writeAll = GL_FALSE;
 
    if (span->start >= span->end)
@@ -110,64 +224,3 @@ _mesa_alpha_test( const GLcontext *ctx, struct sw_span *span,
    else
      return 1;
 }
-
-
-/*
- * Apply the alpha test to a span of pixels.
- * In:  rgba - array of pixels
- * In/Out:  mask - current pixel mask.  Pixels which fail the alpha test
- *                 will set the corresponding mask flag to 0.
- * Return:  0 = all pixels in the span failed the alpha test.
- *          1 = one or more pixels passed the alpha test.
- */
-GLint
-_old_alpha_test( const GLcontext *ctx,
-                GLuint n, CONST GLchan rgba[][4], GLubyte mask[] )
-{
-   GLuint i;
-   const GLchan ref = ctx->Color.AlphaRef;
-
-   /* switch cases ordered from most frequent to less frequent */
-   switch (ctx->Color.AlphaFunc) {
-      case GL_LESS:
-         for (i=0;i<n;i++) {
-           mask[i] &= (rgba[i][ACOMP] < ref);
-        }
-        return 1;
-      case GL_LEQUAL:
-         for (i=0;i<n;i++)
-           mask[i] &= (rgba[i][ACOMP] <= ref);
-        return 1;
-      case GL_GEQUAL:
-         for (i=0;i<n;i++) {
-           mask[i] &= (rgba[i][ACOMP] >= ref);
-        }
-        return 1;
-      case GL_GREATER:
-         for (i=0;i<n;i++) {
-           mask[i] &= (rgba[i][ACOMP] > ref);
-        }
-        return 1;
-      case GL_NOTEQUAL:
-         for (i=0;i<n;i++) {
-           mask[i] &= (rgba[i][ACOMP] != ref);
-        }
-        return 1;
-      case GL_EQUAL:
-         for (i=0;i<n;i++) {
-           mask[i] &= (rgba[i][ACOMP] == ref);
-        }
-        return 1;
-      case GL_ALWAYS:
-        /* do nothing */
-        return 1;
-      case GL_NEVER:
-         /* caller should check for zero! */
-        return 0;
-      default:
-        _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
-         return 0;
-   }
-   /* Never get here */
-   /*return 1;*/
-}