s_logic.c revision 5ec5c6b22262e83706f8b1c42d9e6b5b432a7f8b
1/* 2 * Mesa 3-D graphics library 3 * Version: 6.3 4 * 5 * Copyright (C) 1999-2005 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#include "glheader.h" 27#include "context.h" 28#include "imports.h" 29#include "macros.h" 30 31#include "s_context.h" 32#include "s_logic.h" 33#include "s_span.h" 34 35 36#define LOGIC_OP_LOOP(MODE) \ 37do { \ 38 GLuint i; \ 39 switch (MODE) { \ 40 case GL_CLEAR: \ 41 for (i = 0; i < n; i++) { \ 42 if (mask[i]) { \ 43 src[i] = 0; \ 44 } \ 45 } \ 46 break; \ 47 case GL_SET: \ 48 for (i = 0; i < n; i++) { \ 49 if (mask[i]) { \ 50 src[i] = ~0; \ 51 } \ 52 } \ 53 break; \ 54 case GL_COPY: \ 55 /* do nothing */ \ 56 break; \ 57 case GL_COPY_INVERTED: \ 58 for (i = 0; i < n; i++) { \ 59 if (mask[i]) { \ 60 src[i] = ~src[i]; \ 61 } \ 62 } \ 63 break; \ 64 case GL_NOOP: \ 65 for (i = 0; i < n; i++) { \ 66 if (mask[i]) { \ 67 src[i] = dest[i]; \ 68 } \ 69 } \ 70 break; \ 71 case GL_INVERT: \ 72 for (i = 0; i < n; i++) { \ 73 if (mask[i]) { \ 74 src[i] = ~dest[i]; \ 75 } \ 76 } \ 77 break; \ 78 case GL_AND: \ 79 for (i = 0; i < n; i++) { \ 80 if (mask[i]) { \ 81 src[i] &= dest[i]; \ 82 } \ 83 } \ 84 break; \ 85 case GL_NAND: \ 86 for (i = 0; i < n; i++) { \ 87 if (mask[i]) { \ 88 src[i] = ~(src[i] & dest[i]); \ 89 } \ 90 } \ 91 break; \ 92 case GL_OR: \ 93 for (i = 0; i < n; i++) { \ 94 if (mask[i]) { \ 95 src[i] |= dest[i]; \ 96 } \ 97 } \ 98 break; \ 99 case GL_NOR: \ 100 for (i = 0; i < n; i++) { \ 101 if (mask[i]) { \ 102 src[i] = ~(src[i] | dest[i]); \ 103 } \ 104 } \ 105 break; \ 106 case GL_XOR: \ 107 for (i = 0; i < n; i++) { \ 108 if (mask[i]) { \ 109 src[i] ^= dest[i]; \ 110 } \ 111 } \ 112 break; \ 113 case GL_EQUIV: \ 114 for (i = 0; i < n; i++) { \ 115 if (mask[i]) { \ 116 src[i] = ~(src[i] ^ dest[i]); \ 117 } \ 118 } \ 119 break; \ 120 case GL_AND_REVERSE: \ 121 for (i = 0; i < n; i++) { \ 122 if (mask[i]) { \ 123 src[i] = src[i] & ~dest[i]; \ 124 } \ 125 } \ 126 break; \ 127 case GL_AND_INVERTED: \ 128 for (i = 0; i < n; i++) { \ 129 if (mask[i]) { \ 130 src[i] = ~src[i] & dest[i]; \ 131 } \ 132 } \ 133 break; \ 134 case GL_OR_REVERSE: \ 135 for (i = 0; i < n; i++) { \ 136 if (mask[i]) { \ 137 src[i] = src[i] | ~dest[i]; \ 138 } \ 139 } \ 140 break; \ 141 case GL_OR_INVERTED: \ 142 for (i = 0; i < n; i++) { \ 143 if (mask[i]) { \ 144 src[i] = ~src[i] | dest[i]; \ 145 } \ 146 } \ 147 break; \ 148 default: \ 149 _mesa_problem(ctx, "bad logicop mode");\ 150 } \ 151} while (0) 152 153 154 155static void 156logicop_ubyte(GLcontext *ctx, GLuint n, GLubyte src[], const GLubyte dest[], 157 const GLubyte mask[]) 158{ 159 LOGIC_OP_LOOP(ctx->Color.LogicOp); 160} 161 162 163static void 164logicop_ushort(GLcontext *ctx, GLuint n, GLushort src[], const GLushort dest[], 165 const GLubyte mask[]) 166{ 167 LOGIC_OP_LOOP(ctx->Color.LogicOp); 168} 169 170 171static void 172logicop_uint(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[], 173 const GLubyte mask[]) 174{ 175 LOGIC_OP_LOOP(ctx->Color.LogicOp); 176} 177 178 179 180/* 181 * Apply the current logic operator to a span of CI pixels. This is only 182 * used if the device driver can't do logic ops. 183 */ 184void 185_swrast_logicop_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb, 186 const struct sw_span *span, GLuint index[]) 187{ 188 GLuint dest[MAX_WIDTH]; 189 190 ASSERT(span->end < MAX_WIDTH); 191 ASSERT(rb->DataType == GL_UNSIGNED_INT); 192 193 /* Read dest values from frame buffer */ 194 if (span->arrayMask & SPAN_XY) { 195 rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y, dest); 196 } 197 else { 198 rb->GetRow(ctx, rb, span->end, span->x, span->y, dest); 199 } 200 201 logicop_uint(ctx, span->end, index, dest, span->array->mask); 202} 203 204 205/** 206 * Apply the current logic operator to a span of RGBA pixels. 207 * We can handle horizontal runs of pixels (spans) or arrays of x/y 208 * pixel coordinates. 209 */ 210void 211_swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb, 212 const struct sw_span *span, GLchan rgba[][4]) 213{ 214 GLchan dest[MAX_WIDTH][4]; 215 216 ASSERT(span->end < MAX_WIDTH); 217 ASSERT(span->arrayMask & SPAN_RGBA); 218 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 219 220 if (span->arrayMask & SPAN_XY) { 221 rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y, dest); 222 } 223 else { 224 _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y, dest); 225 } 226 227 /* NEW_RENDERBUFFER: XXX make this a runtime test */ 228#if CHAN_TYPE == GL_UNSIGNED_BYTE 229 /* treat 4*GLubyte as GLuint */ 230 logicop_uint(ctx, span->end, (GLuint *) rgba, 231 (const GLuint *) dest, span->array->mask); 232#elif CHAN_TYPE == GL_UNSIGNED_SHORT 233 logicop_ushort(ctx, 4 * span->end, (GLushort *) rgba, 234 (const GLushort *) dest, span->array->mask); 235#elif CHAN_TYPE == GL_FLOAT 236 logicop_uint(ctx, 4 * span->end, (GLuint *) rgba, 237 (const GLuint *) dest, span->array->mask); 238#endif 239 (void) logicop_ubyte; 240 (void) logicop_ushort; 241 (void) logicop_uint; 242} 243