083c3c4402e947e031f6e31947e9c7a5485f1a12
[mesa.git] / src / mesa / swrast / s_logic.c
1 /* $Id: s_logic.c,v 1.11 2002/08/07 00:45:07 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 "macros.h"
31
32 #include "s_alphabuf.h"
33 #include "s_context.h"
34 #include "s_logic.h"
35 #include "s_span.h"
36
37
38
39 /*
40 * Apply logic op to array of CI pixels.
41 */
42 static void
43 index_logicop( GLcontext *ctx, GLuint n, GLuint index[], const GLuint dest[],
44 const GLubyte mask[] )
45 {
46 GLuint i;
47 switch (ctx->Color.LogicOp) {
48 case GL_CLEAR:
49 for (i=0;i<n;i++) {
50 if (mask[i]) {
51 index[i] = 0;
52 }
53 }
54 break;
55 case GL_SET:
56 for (i=0;i<n;i++) {
57 if (mask[i]) {
58 index[i] = ~0;
59 }
60 }
61 break;
62 case GL_COPY:
63 /* do nothing */
64 break;
65 case GL_COPY_INVERTED:
66 for (i=0;i<n;i++) {
67 if (mask[i]) {
68 index[i] = ~index[i];
69 }
70 }
71 break;
72 case GL_NOOP:
73 for (i=0;i<n;i++) {
74 if (mask[i]) {
75 index[i] = dest[i];
76 }
77 }
78 break;
79 case GL_INVERT:
80 for (i=0;i<n;i++) {
81 if (mask[i]) {
82 index[i] = ~dest[i];
83 }
84 }
85 break;
86 case GL_AND:
87 for (i=0;i<n;i++) {
88 if (mask[i]) {
89 index[i] &= dest[i];
90 }
91 }
92 break;
93 case GL_NAND:
94 for (i=0;i<n;i++) {
95 if (mask[i]) {
96 index[i] = ~(index[i] & dest[i]);
97 }
98 }
99 break;
100 case GL_OR:
101 for (i=0;i<n;i++) {
102 if (mask[i]) {
103 index[i] |= dest[i];
104 }
105 }
106 break;
107 case GL_NOR:
108 for (i=0;i<n;i++) {
109 if (mask[i]) {
110 index[i] = ~(index[i] | dest[i]);
111 }
112 }
113 break;
114 case GL_XOR:
115 for (i=0;i<n;i++) {
116 if (mask[i]) {
117 index[i] ^= dest[i];
118 }
119 }
120 break;
121 case GL_EQUIV:
122 for (i=0;i<n;i++) {
123 if (mask[i]) {
124 index[i] = ~(index[i] ^ dest[i]);
125 }
126 }
127 break;
128 case GL_AND_REVERSE:
129 for (i=0;i<n;i++) {
130 if (mask[i]) {
131 index[i] = index[i] & ~dest[i];
132 }
133 }
134 break;
135 case GL_AND_INVERTED:
136 for (i=0;i<n;i++) {
137 if (mask[i]) {
138 index[i] = ~index[i] & dest[i];
139 }
140 }
141 break;
142 case GL_OR_REVERSE:
143 for (i=0;i<n;i++) {
144 if (mask[i]) {
145 index[i] = index[i] | ~dest[i];
146 }
147 }
148 break;
149 case GL_OR_INVERTED:
150 for (i=0;i<n;i++) {
151 if (mask[i]) {
152 index[i] = ~index[i] | dest[i];
153 }
154 }
155 break;
156 default:
157 _mesa_problem(ctx, "bad mode in index_logic()");
158 }
159 }
160
161
162
163 /*
164 * Apply the current logic operator to a span of CI pixels. This is only
165 * used if the device driver can't do logic ops.
166 */
167 void
168 _mesa_logicop_ci_span( GLcontext *ctx, const struct sw_span *span,
169 GLuint index[] )
170 {
171 SWcontext *swrast = SWRAST_CONTEXT(ctx);
172 GLuint dest[MAX_WIDTH];
173
174 ASSERT(span->end < MAX_WIDTH);
175
176 /* Read dest values from frame buffer */
177 if (span->arrayMask & SPAN_XY) {
178 (*swrast->Driver.ReadCI32Pixels)( ctx, span->end,
179 span->array->x, span->array->y,
180 dest, span->array->mask );
181 }
182 else {
183 (*swrast->Driver.ReadCI32Span)( ctx, span->end, span->x, span->y, dest );
184 }
185
186 index_logicop( ctx, span->end, index, dest, span->array->mask );
187 }
188
189
190
191 /*
192 * Apply logic operator to rgba pixels.
193 * Input: ctx - the context
194 * n - number of pixels
195 * mask - pixel mask array
196 * In/Out: src - incoming pixels which will be modified
197 * Input: dest - frame buffer values
198 *
199 * Note: Since the R, G, B, and A channels are all treated the same we
200 * process them as 4-byte GLuints instead of four GLubytes.
201 */
202 static void
203 rgba_logicop_ui( const GLcontext *ctx, GLuint n, const GLubyte mask[],
204 GLuint src[], const GLuint dest[] )
205 {
206 GLuint i;
207 switch (ctx->Color.LogicOp) {
208 case GL_CLEAR:
209 for (i=0;i<n;i++) {
210 if (mask[i]) {
211 src[i] = 0;
212 }
213 }
214 break;
215 case GL_SET:
216 for (i=0;i<n;i++) {
217 if (mask[i]) {
218 src[i] = ~0;
219 }
220 }
221 break;
222 case GL_COPY:
223 /* do nothing */
224 break;
225 case GL_COPY_INVERTED:
226 for (i=0;i<n;i++) {
227 if (mask[i]) {
228 src[i] = ~src[i];
229 }
230 }
231 break;
232 case GL_NOOP:
233 for (i=0;i<n;i++) {
234 if (mask[i]) {
235 src[i] = dest[i];
236 }
237 }
238 break;
239 case GL_INVERT:
240 for (i=0;i<n;i++) {
241 if (mask[i]) {
242 src[i] = ~dest[i];
243 }
244 }
245 break;
246 case GL_AND:
247 for (i=0;i<n;i++) {
248 if (mask[i]) {
249 src[i] &= dest[i];
250 }
251 }
252 break;
253 case GL_NAND:
254 for (i=0;i<n;i++) {
255 if (mask[i]) {
256 src[i] = ~(src[i] & dest[i]);
257 }
258 }
259 break;
260 case GL_OR:
261 for (i=0;i<n;i++) {
262 if (mask[i]) {
263 src[i]|= dest[i];
264 }
265 }
266 break;
267 case GL_NOR:
268 for (i=0;i<n;i++) {
269 if (mask[i]) {
270 src[i] = ~(src[i] | dest[i]);
271 }
272 }
273 break;
274 case GL_XOR:
275 for (i=0;i<n;i++) {
276 if (mask[i]) {
277 src[i] ^= dest[i];
278 }
279 }
280 break;
281 case GL_EQUIV:
282 for (i=0;i<n;i++) {
283 if (mask[i]) {
284 src[i] = ~(src[i] ^ dest[i]);
285 }
286 }
287 break;
288 case GL_AND_REVERSE:
289 for (i=0;i<n;i++) {
290 if (mask[i]) {
291 src[i] = src[i] & ~dest[i];
292 }
293 }
294 break;
295 case GL_AND_INVERTED:
296 for (i=0;i<n;i++) {
297 if (mask[i]) {
298 src[i] = ~src[i] & dest[i];
299 }
300 }
301 break;
302 case GL_OR_REVERSE:
303 for (i=0;i<n;i++) {
304 if (mask[i]) {
305 src[i] = src[i] | ~dest[i];
306 }
307 }
308 break;
309 case GL_OR_INVERTED:
310 for (i=0;i<n;i++) {
311 if (mask[i]) {
312 src[i] = ~src[i] | dest[i];
313 }
314 }
315 break;
316 default:
317 /* should never happen */
318 _mesa_problem(ctx, "Bad function in rgba_logicop");
319 }
320 }
321
322
323 /*
324 * As above, but operate on GLchan values
325 * Note: need to pass n = numPixels * 4.
326 */
327 static void
328 rgba_logicop_chan( const GLcontext *ctx, GLuint n, const GLubyte mask[],
329 GLchan srcPtr[], const GLchan destPtr[] )
330 {
331 #if CHAN_TYPE == GL_FLOAT
332 GLuint *src = (GLuint *) srcPtr;
333 const GLuint *dest = (const GLuint *) destPtr;
334 GLuint i;
335 ASSERT(sizeof(GLfloat) == sizeof(GLuint));
336 #else
337 GLchan *src = srcPtr;
338 const GLchan *dest = destPtr;
339 GLuint i;
340 #endif
341
342 switch (ctx->Color.LogicOp) {
343 case GL_CLEAR:
344 for (i=0;i<n;i++) {
345 if (mask[i]) {
346 src[i] = 0;
347 }
348 }
349 break;
350 case GL_SET:
351 for (i=0;i<n;i++) {
352 if (mask[i]) {
353 src[i] = ~0;
354 }
355 }
356 break;
357 case GL_COPY:
358 /* do nothing */
359 break;
360 case GL_COPY_INVERTED:
361 for (i=0;i<n;i++) {
362 if (mask[i]) {
363 src[i] = ~src[i];
364 }
365 }
366 break;
367 case GL_NOOP:
368 for (i=0;i<n;i++) {
369 if (mask[i]) {
370 src[i] = dest[i];
371 }
372 }
373 break;
374 case GL_INVERT:
375 for (i=0;i<n;i++) {
376 if (mask[i]) {
377 src[i] = ~dest[i];
378 }
379 }
380 break;
381 case GL_AND:
382 for (i=0;i<n;i++) {
383 if (mask[i]) {
384 src[i] &= dest[i];
385 }
386 }
387 break;
388 case GL_NAND:
389 for (i=0;i<n;i++) {
390 if (mask[i]) {
391 src[i] = ~(src[i] & dest[i]);
392 }
393 }
394 break;
395 case GL_OR:
396 for (i=0;i<n;i++) {
397 if (mask[i]) {
398 src[i]|= dest[i];
399 }
400 }
401 break;
402 case GL_NOR:
403 for (i=0;i<n;i++) {
404 if (mask[i]) {
405 src[i] = ~(src[i] | dest[i]);
406 }
407 }
408 break;
409 case GL_XOR:
410 for (i=0;i<n;i++) {
411 if (mask[i]) {
412 src[i] ^= dest[i];
413 }
414 }
415 break;
416 case GL_EQUIV:
417 for (i=0;i<n;i++) {
418 if (mask[i]) {
419 src[i] = ~(src[i] ^ dest[i]);
420 }
421 }
422 break;
423 case GL_AND_REVERSE:
424 for (i=0;i<n;i++) {
425 if (mask[i]) {
426 src[i] = src[i] & ~dest[i];
427 }
428 }
429 break;
430 case GL_AND_INVERTED:
431 for (i=0;i<n;i++) {
432 if (mask[i]) {
433 src[i] = ~src[i] & dest[i];
434 }
435 }
436 break;
437 case GL_OR_REVERSE:
438 for (i=0;i<n;i++) {
439 if (mask[i]) {
440 src[i] = src[i] | ~dest[i];
441 }
442 }
443 break;
444 case GL_OR_INVERTED:
445 for (i=0;i<n;i++) {
446 if (mask[i]) {
447 src[i] = ~src[i] | dest[i];
448 }
449 }
450 break;
451 default:
452 /* should never happen */
453 _mesa_problem(ctx, "Bad function in rgba_logicop");
454 }
455 }
456
457
458
459 /*
460 * Apply the current logic operator to a span of RGBA pixels.
461 * We can handle horizontal runs of pixels (spans) or arrays of x/y
462 * pixel coordinates.
463 */
464 void
465 _mesa_logicop_rgba_span( GLcontext *ctx, const struct sw_span *span,
466 GLchan rgba[][4] )
467 {
468 SWcontext *swrast = SWRAST_CONTEXT(ctx);
469 GLchan dest[MAX_WIDTH][4];
470
471 ASSERT(span->end < MAX_WIDTH);
472 ASSERT(span->arrayMask & SPAN_RGBA);
473
474 if (span->arrayMask & SPAN_XY) {
475 (*swrast->Driver.ReadRGBAPixels)(ctx, span->end,
476 span->array->x, span->array->y,
477 dest, span->array->mask);
478 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
479 _mesa_read_alpha_pixels(ctx, span->end,
480 span->array->x, span->array->y,
481 dest, span->array->mask);
482 }
483 }
484 else {
485 _mesa_read_rgba_span(ctx, ctx->DrawBuffer, span->end,
486 span->x, span->y, dest);
487 }
488
489 if (sizeof(GLchan) * 4 == sizeof(GLuint)) {
490 rgba_logicop_ui(ctx, span->end, span->array->mask,
491 (GLuint *) rgba, (const GLuint *) dest);
492 }
493 else {
494 rgba_logicop_chan(ctx, 4 * span->end, span->array->mask,
495 (GLchan *) rgba, (const GLchan *) dest);
496 }
497 }