template code for span functions for flat, memory-based frame buffers
[mesa.git] / src / mesa / swrast / s_alpha.c
index e6bd0c32489c2033373138b0f75a05724ba91c00..5cbfe8617a58bedfafb42bb465ee8d5d3f817e0d 100644 (file)
@@ -1,21 +1,21 @@
-/* $Id: s_alpha.c,v 1.3 2001/03/03 20:33:30 brianp Exp $ */
+/* $Id: s_alpha.c,v 1.12 2002/10/04 19:10:12 brianp Exp $ */
 
 /*
  * Mesa 3-D graphics library
- * Version:  3.3
- * 
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
- * 
+ * Version:  4.1
+ *
+ * Copyright (C) 1999-2002  Brian Paul   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, sublicense,
  * 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 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 NONINFRINGEMENT.  IN NO EVENT SHALL
  * 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:  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.
+/**
+ * \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,
-                  GLuint n, CONST GLchan rgba[][4], GLubyte mask[] )
+_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;
-   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;
+   CLAMPED_FLOAT_TO_CHAN(ref, ctx->Color.AlphaRef);
+
+   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;
+      }
    }
-   /* Never get here */
-   /*return 1;*/
+   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))
+     span->start ++;
+
+   while ((span->end >= span->start)  &&
+          (mask[span->end] == 0))
+     span->end --;
+#endif
+
+   span->writeAll = GL_FALSE;
+
+   if (span->start >= span->end)
+     return 0;
+   else
+     return 1;
 }