mesa: implement core Mesa support for GL_ARB_draw_instanced
[mesa.git] / src / mesa / swrast / s_alpha.c
index 5cbfe8617a58bedfafb42bb465ee8d5d3f817e0d..509477433a535f7a147558fe057e9e1274d59cd0 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: s_alpha.c,v 1.12 2002/10/04 19:10:12 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  4.1
+ * Version:  6.5.2
  *
- * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ * 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"),
  * \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)
+
+
+
 /**
- * \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.
+ * 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, struct sw_span *span )
+_swrast_alpha_test(const GLcontext *ctx, SWspan *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;
 
-   CLAMPED_FLOAT_TO_CHAN(ref, ctx->Color.AlphaRef);
+   if (ctx->Color.AlphaFunc == GL_ALWAYS) {
+      /* do nothing */
+      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 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;
+      /* 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 {
-      /* Use the interpolation values */
-#if CHAN_TYPE == GL_FLOAT
-      const GLfloat alphaStep = span->alphaStep;
-      GLfloat alpha = span->alpha;
+      /* Interpolate alpha values */
       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;
+      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
-      /* 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;
+      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);
       }
-#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;
+   /* XXX examine mask[] values? */
+   return 1;
 }