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 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