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