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