• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)		\
39 do {						\
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  */
91 GLint
_swrast_alpha_test(const struct gl_context * ctx,SWspan * span)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