mesa: implement core Mesa support for GL_ARB_draw_instanced
[mesa.git] / src / mesa / swrast / s_alpha.c
index 6440ffb18fa0c16295af94247834b2783a0c969a..509477433a535f7a147558fe057e9e1274d59cd0 100644 (file)
@@ -1,21 +1,19 @@
-/* $Id: s_alpha.c,v 1.2 2000/11/13 20:02:57 keithw Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.3
- * 
- * Copyright (C) 1999-2000  Brian Paul   All Rights Reserved.
- * 
+ * Version:  6.5.2
+ *
+ * Copyright (C) 1999-2006  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 "colormac.h"
-#include "macros.h"
-#include "mmath.h"
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/macros.h"
 
 #include "s_alpha.h"
+#include "s_context.h"
 
 
+#define ALPHA_TEST(ALPHA, LOOP_CODE)           \
+do {                                           \
+   switch (ctx->Color.AlphaFunc) {             \
+      case GL_LESS:                            \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA < ref);          \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_LEQUAL:                          \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA <= ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_GEQUAL:                          \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA >= ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_GREATER:                         \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA > ref);          \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_NOTEQUAL:                                \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA != ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      case GL_EQUAL:                           \
+         for (i = 0; i < n; i++) {             \
+            mask[i] &= (ALPHA == ref);         \
+            LOOP_CODE;                         \
+         }                                     \
+         break;                                        \
+      default:                                 \
+         _mesa_problem(ctx, "Invalid alpha test in _swrast_alpha_test" ); \
+         return 0;                             \
+   }                                           \
+} while (0)
 
 
 
-/*
- * 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.
+/**
+ * Perform the alpha test for an array of pixels.
+ * For pixels that fail the test, mask[i] will be set to 0.
+ * \return  0 if all pixels in the span failed the alpha test,
+ *          1 if one or more pixels passed the alpha test.
  */
 GLint
-_mesa_alpha_test( const GLcontext *ctx,
-                  GLuint n, CONST GLchan rgba[][4], GLubyte mask[] )
+_swrast_alpha_test(const GLcontext *ctx, SWspan *span)
 {
+   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:
-        gl_problem( ctx, "Invalid alpha test in gl_alpha_test" );
-         return 0;
+   if (ctx->Color.AlphaFunc == GL_ALWAYS) {
+      /* do nothing */
+      return 1;
    }
-   /* Never get here */
-   /*return 1;*/
+   else if (ctx->Color.AlphaFunc == GL_NEVER) {
+      /* All pixels failed - caller should check for this return value and
+       * act accordingly.
+       */
+      span->writeAll = GL_FALSE;
+      return 0;
+   }
+
+   if (span->arrayMask & SPAN_RGBA) {
+      /* Use array's alpha values */
+      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+         GLubyte (*rgba)[4] = span->array->rgba8;
+         GLubyte ref;
+         CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(rgba[i][ACOMP], ;);
+      }
+      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+         GLushort (*rgba)[4] = span->array->rgba16;
+         GLushort ref;
+         CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(rgba[i][ACOMP], ;);
+      }
+      else {
+         GLfloat (*rgba)[4] = span->array->attribs[FRAG_ATTRIB_COL0];
+         const GLfloat ref = ctx->Color.AlphaRef;
+         ALPHA_TEST(rgba[i][ACOMP], ;);
+      }
+   }
+   else {
+      /* Interpolate alpha values */
+      ASSERT(span->interpMask & SPAN_RGBA);
+      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
+         const GLfixed alphaStep = span->alphaStep;
+         GLfixed alpha = span->alpha;
+         GLubyte ref;
+         CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
+      }
+      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
+         const GLfixed alphaStep = span->alphaStep;
+         GLfixed alpha = span->alpha;
+         GLushort ref;
+         CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
+         ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
+      }
+      else {
+         const GLfloat alphaStep = FixedToFloat(span->alphaStep);
+         GLfloat alpha = FixedToFloat(span->alpha);
+         const GLfloat ref = ctx->Color.AlphaRef;
+         ALPHA_TEST(alpha, alpha += alphaStep);
+      }
+   }
+
+   span->writeAll = GL_FALSE;
+
+   /* XXX examine mask[] values? */
+   return 1;
 }