-/* $Id: s_alpha.c,v 1.5 2002/01/21 18:12:34 brianp Exp $ */
-
/*
* Mesa 3-D graphics library
- * Version: 4.1
*
- * 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"),
* 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
- * BRIAN PAUL 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.
+ * THE AUTHORS OR COPYRIGHT HOLDERS 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.
*/
+/**
+ * \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"
-
-
-/*
- * 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.
+#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)
+
+
+
+/**
+ * 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,
- CONST GLchan rgba[][4])
+_swrast_alpha_test(const struct gl_context *ctx, SWspan *span)
{
+ const GLuint n = span->end;
+ GLubyte *mask = span->array->mask;
GLuint i;
- const GLchan ref = ctx->Color.AlphaRef;
- GLubyte *mask = span->mask;
-
- ASSERT (span->filledMask == GL_TRUE);
- ASSERT (span->filledAlpha == GL_TRUE);
- SW_SPAN_SET_FLAG(span->testedAlpha);
-
-
- /* 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 (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;
}
- while ((span->start <= span->end) &&
- (mask[span->start] == 0))
- span->start ++;
-
- while ((span->end >= span->start) &&
- (mask[span->end] == 0))
- span->end --;
+ 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[VARYING_SLOT_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;
- if (span->start >= span->end)
- return 0;
- 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;*/
+ /* XXX examine mask[] values? */
+ return 1;
}