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