s_alpha.c revision ceb39f4f8dc4863fde17d668c752533a2184476e
1/* $Id: s_alpha.c,v 1.8 2002/01/31 00:27:43 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  4.1
6 *
7 * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
8 *
9 * Permission is hereby granted, free of charge, to any person obtaining a
10 * copy of this software and associated documentation files (the "Software"),
11 * to deal in the Software without restriction, including without limitation
12 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
13 * and/or sell copies of the Software, and to permit persons to whom the
14 * Software is furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be included
17 * in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
23 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 */
26
27
28#include "glheader.h"
29#include "context.h"
30#include "colormac.h"
31#include "macros.h"
32#include "mmath.h"
33
34#include "s_alpha.h"
35#include "s_context.h"
36
37
38/*
39 * Apply the alpha test to a span of pixels.
40 * In:  rgba - array of pixels
41 * In/Out:  span -
42 * Return:  0 = all pixels in the span failed the alpha test.
43 *          1 = one or more pixels passed the alpha test.
44 */
45GLint
46_mesa_alpha_test( const GLcontext *ctx, struct sw_span *span )
47{
48   const GLchan (*rgba)[4] = (const GLchan (*)[4]) span->color.rgba;
49   const GLchan ref = ctx->Color.AlphaRef;
50   const GLuint n = span->end;
51   GLubyte *mask = span->mask;
52   GLuint i;
53
54   if (span->arrayMask & SPAN_RGBA) {
55      /* Use the array values */
56      switch (ctx->Color.AlphaFunc) {
57         case GL_LESS:
58            for (i = 0; i < n; i++)
59               mask[i] &= (rgba[i][ACOMP] < ref);
60            break;
61         case GL_LEQUAL:
62            for (i = 0; i < n; i++)
63               mask[i] &= (rgba[i][ACOMP] <= ref);
64            break;
65         case GL_GEQUAL:
66            for (i = 0; i < n; i++)
67               mask[i] &= (rgba[i][ACOMP] >= ref);
68            break;
69         case GL_GREATER:
70            for (i = 0; i < n; i++)
71               mask[i] &= (rgba[i][ACOMP] > ref);
72            break;
73         case GL_NOTEQUAL:
74            for (i = 0; i < n; i++)
75               mask[i] &= (rgba[i][ACOMP] != ref);
76            break;
77         case GL_EQUAL:
78            for (i = 0; i < n; i++)
79               mask[i] &= (rgba[i][ACOMP] == ref);
80            break;
81         case GL_ALWAYS:
82            /* do nothing */
83            return 1;
84         case GL_NEVER:
85            /* caller should check for zero! */
86            span->writeAll = GL_FALSE;
87            return 0;
88         default:
89            _mesa_problem( ctx, "Invalid alpha test in _mesa_alpha_test" );
90            return 0;
91      }
92   }
93   else {
94      /* Use the interpolation values */
95#if CHAN_TYPE == GL_FLOAT
96      const GLfloat alphaStep = span->alphaStep;
97      GLfloat alpha = span->alpha;
98      ASSERT(span->interpMask & SPAN_RGBA);
99      switch (ctx->Color.AlphaFunc) {
100         case GL_LESS:
101            for (i = 0; i < n; i++) {
102               mask[i] &= (alpha < ref);
103               alpha += alphaStep;
104            }
105            break;
106         case GL_LEQUAL:
107            for (i = 0; i < n; i++) {
108               mask[i] &= (alpha <= ref);
109               alpha += alphaStep;
110            }
111            break;
112         case GL_GEQUAL:
113            for (i = 0; i < n; i++) {
114               mask[i] &= (alpha >= ref);
115               alpha += alphaStep;
116            }
117            break;
118         case GL_GREATER:
119            for (i = 0; i < n; i++) {
120               mask[i] &= (alpha > ref);
121               alpha += alphaStep;
122            }
123            break;
124         case GL_NOTEQUAL:
125            for (i = 0; i < n; i++) {
126               mask[i] &= (alpha != ref);
127               alpha += alphaStep;
128            }
129            break;
130         case GL_EQUAL:
131            for (i = 0; i < n; i++) {
132               mask[i] &= (alpha == ref);
133               alpha += alphaStep;
134            }
135            break;
136         case GL_ALWAYS:
137            /* do nothing */
138            return 1;
139         case GL_NEVER:
140            /* caller should check for zero! */
141            span->writeAll = GL_FALSE;
142            return 0;
143         default:
144            _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
145            return 0;
146      }
147#else
148      /* 8 or 16-bit channel interpolation */
149      const GLfixed alphaStep = span->alphaStep;
150      GLfixed alpha = span->alpha;
151      ASSERT(span->interpMask & SPAN_RGBA);
152      switch (ctx->Color.AlphaFunc) {
153         case GL_LESS:
154            for (i = 0; i < n; i++) {
155               mask[i] &= (FixedToChan(alpha) < ref);
156               alpha += alphaStep;
157            }
158            break;
159         case GL_LEQUAL:
160            for (i = 0; i < n; i++) {
161               mask[i] &= (FixedToChan(alpha) <= ref);
162               alpha += alphaStep;
163            }
164            break;
165         case GL_GEQUAL:
166            for (i = 0; i < n; i++) {
167               mask[i] &= (FixedToChan(alpha) >= ref);
168               alpha += alphaStep;
169            }
170            break;
171         case GL_GREATER:
172            for (i = 0; i < n; i++) {
173               mask[i] &= (FixedToChan(alpha) > ref);
174               alpha += alphaStep;
175            }
176            break;
177         case GL_NOTEQUAL:
178            for (i = 0; i < n; i++) {
179               mask[i] &= (FixedToChan(alpha) != ref);
180               alpha += alphaStep;
181            }
182            break;
183         case GL_EQUAL:
184            for (i = 0; i < n; i++) {
185               mask[i] &= (FixedToChan(alpha) == ref);
186               alpha += alphaStep;
187            }
188            break;
189         case GL_ALWAYS:
190            /* do nothing */
191            return 1;
192         case GL_NEVER:
193            /* caller should check for zero! */
194            span->writeAll = GL_FALSE;
195            return 0;
196         default:
197            _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
198            return 0;
199      }
200#endif /* CHAN_TYPE */
201   }
202
203#if 0
204   /* XXXX This causes conformance failures!!!! */
205   while ((span->start <= span->end)  &&
206          (mask[span->start] == 0))
207     span->start ++;
208
209   while ((span->end >= span->start)  &&
210          (mask[span->end] == 0))
211     span->end --;
212#endif
213
214   span->writeAll = GL_FALSE;
215
216   if (span->start >= span->end)
217     return 0;
218   else
219     return 1;
220}
221
222
223/*
224 * Apply the alpha test to a span of pixels.
225 * In:  rgba - array of pixels
226 * In/Out:  mask - current pixel mask.  Pixels which fail the alpha test
227 *                 will set the corresponding mask flag to 0.
228 * Return:  0 = all pixels in the span failed the alpha test.
229 *          1 = one or more pixels passed the alpha test.
230 */
231GLint
232_old_alpha_test( const GLcontext *ctx,
233                 GLuint n, CONST GLchan rgba[][4], GLubyte mask[] )
234{
235   GLuint i;
236   const GLchan ref = ctx->Color.AlphaRef;
237
238   /* switch cases ordered from most frequent to less frequent */
239   switch (ctx->Color.AlphaFunc) {
240      case GL_LESS:
241         for (i=0;i<n;i++) {
242	    mask[i] &= (rgba[i][ACOMP] < ref);
243	 }
244	 return 1;
245      case GL_LEQUAL:
246         for (i=0;i<n;i++)
247	    mask[i] &= (rgba[i][ACOMP] <= ref);
248	 return 1;
249      case GL_GEQUAL:
250         for (i=0;i<n;i++) {
251	    mask[i] &= (rgba[i][ACOMP] >= ref);
252	 }
253	 return 1;
254      case GL_GREATER:
255         for (i=0;i<n;i++) {
256	    mask[i] &= (rgba[i][ACOMP] > ref);
257	 }
258	 return 1;
259      case GL_NOTEQUAL:
260         for (i=0;i<n;i++) {
261	    mask[i] &= (rgba[i][ACOMP] != ref);
262	 }
263	 return 1;
264      case GL_EQUAL:
265         for (i=0;i<n;i++) {
266	    mask[i] &= (rgba[i][ACOMP] == ref);
267	 }
268	 return 1;
269      case GL_ALWAYS:
270	 /* do nothing */
271	 return 1;
272      case GL_NEVER:
273         /* caller should check for zero! */
274	 return 0;
275      default:
276	 _mesa_problem( ctx, "Invalid alpha test in gl_alpha_test" );
277         return 0;
278   }
279   /* Never get here */
280   /*return 1;*/
281}
282