s_alpha.c revision 01e04c3f
1/*
2 * Mesa 3-D graphics library
3 *
4 * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 * OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25/**
26 * \file swrast/s_alpha.c
27 * \brief Functions to apply alpha test.
28 */
29
30#include "main/glheader.h"
31#include "main/context.h"
32#include "main/macros.h"
33
34#include "s_alpha.h"
35#include "s_context.h"
36
37
38#define ALPHA_TEST(ALPHA, LOOP_CODE)		\
39do {						\
40   switch (ctx->Color.AlphaFunc) {		\
41      case GL_LESS:				\
42         for (i = 0; i < n; i++) {		\
43            mask[i] &= (ALPHA < ref);		\
44            LOOP_CODE;				\
45         }					\
46         break;					\
47      case GL_LEQUAL:				\
48         for (i = 0; i < n; i++) {		\
49            mask[i] &= (ALPHA <= ref);		\
50            LOOP_CODE;				\
51         }					\
52         break;					\
53      case GL_GEQUAL:				\
54         for (i = 0; i < n; i++) {		\
55            mask[i] &= (ALPHA >= ref);		\
56            LOOP_CODE;				\
57         }					\
58         break;					\
59      case GL_GREATER:				\
60         for (i = 0; i < n; i++) {		\
61            mask[i] &= (ALPHA > ref);		\
62            LOOP_CODE;				\
63         }					\
64         break;					\
65      case GL_NOTEQUAL:				\
66         for (i = 0; i < n; i++) {		\
67            mask[i] &= (ALPHA != ref);		\
68            LOOP_CODE;				\
69         }					\
70         break;					\
71      case GL_EQUAL:				\
72         for (i = 0; i < n; i++) {		\
73            mask[i] &= (ALPHA == ref);		\
74            LOOP_CODE;				\
75         }					\
76         break;					\
77      default:					\
78         _mesa_problem(ctx, "Invalid alpha test in _swrast_alpha_test" ); \
79         return 0;				\
80   }						\
81} while (0)
82
83
84
85/**
86 * Perform the alpha test for an array of pixels.
87 * For pixels that fail the test, mask[i] will be set to 0.
88 * \return  0 if all pixels in the span failed the alpha test,
89 *          1 if one or more pixels passed the alpha test.
90 */
91GLint
92_swrast_alpha_test(const struct gl_context *ctx, SWspan *span)
93{
94   const GLuint n = span->end;
95   GLubyte *mask = span->array->mask;
96   GLuint i;
97
98   if (ctx->Color.AlphaFunc == GL_ALWAYS) {
99      /* do nothing */
100      return 1;
101   }
102   else if (ctx->Color.AlphaFunc == GL_NEVER) {
103      /* All pixels failed - caller should check for this return value and
104       * act accordingly.
105       */
106      span->writeAll = GL_FALSE;
107      return 0;
108   }
109
110   if (span->arrayMask & SPAN_RGBA) {
111      /* Use array's alpha values */
112      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
113         GLubyte (*rgba)[4] = span->array->rgba8;
114         GLubyte ref;
115         CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
116         ALPHA_TEST(rgba[i][ACOMP], ;);
117      }
118      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
119         GLushort (*rgba)[4] = span->array->rgba16;
120         GLushort ref;
121         CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
122         ALPHA_TEST(rgba[i][ACOMP], ;);
123      }
124      else {
125         GLfloat (*rgba)[4] = span->array->attribs[VARYING_SLOT_COL0];
126         const GLfloat ref = ctx->Color.AlphaRef;
127         ALPHA_TEST(rgba[i][ACOMP], ;);
128      }
129   }
130   else {
131      /* Interpolate alpha values */
132      assert(span->interpMask & SPAN_RGBA);
133      if (span->array->ChanType == GL_UNSIGNED_BYTE) {
134         const GLfixed alphaStep = span->alphaStep;
135         GLfixed alpha = span->alpha;
136         GLubyte ref;
137         CLAMPED_FLOAT_TO_UBYTE(ref, ctx->Color.AlphaRef);
138         ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
139      }
140      else if (span->array->ChanType == GL_UNSIGNED_SHORT) {
141         const GLfixed alphaStep = span->alphaStep;
142         GLfixed alpha = span->alpha;
143         GLushort ref;
144         CLAMPED_FLOAT_TO_USHORT(ref, ctx->Color.AlphaRef);
145         ALPHA_TEST(FixedToInt(alpha), alpha += alphaStep);
146      }
147      else {
148         const GLfloat alphaStep = FixedToFloat(span->alphaStep);
149         GLfloat alpha = FixedToFloat(span->alpha);
150         const GLfloat ref = ctx->Color.AlphaRef;
151         ALPHA_TEST(alpha, alpha += alphaStep);
152      }
153   }
154
155   span->writeAll = GL_FALSE;
156
157   /* XXX examine mask[] values? */
158   return 1;
159}
160