277ace6fa6059ebd2db6f6ed9bbea33c88ddd339
[mesa.git] / src / mesa / swrast / s_logic.c
1 /* $Id: s_logic.c,v 1.12 2002/10/24 23:57:24 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 "imports.h"
31 #include "macros.h"
32
33 #include "s_alphabuf.h"
34 #include "s_context.h"
35 #include "s_logic.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,
180 span->array->x, span->array->y,
181 dest, span->array->mask );
182 }
183 else {
184 (*swrast->Driver.ReadCI32Span)( ctx, span->end, span->x, span->y, dest );
185 }
186
187 index_logicop( ctx, span->end, index, dest, span->array->mask );
188 }
189
190
191
192 /*
193 * Apply logic operator to rgba pixels.
194 * Input: ctx - the context
195 * n - number of pixels
196 * mask - pixel mask array
197 * In/Out: src - incoming pixels which will be modified
198 * Input: dest - frame buffer values
199 *
200 * Note: Since the R, G, B, and A channels are all treated the same we
201 * process them as 4-byte GLuints instead of four GLubytes.
202 */
203 static void
204 rgba_logicop_ui( const GLcontext *ctx, GLuint n, const GLubyte mask[],
205 GLuint src[], const GLuint dest[] )
206 {
207 GLuint i;
208 switch (ctx->Color.LogicOp) {
209 case GL_CLEAR:
210 for (i=0;i<n;i++) {
211 if (mask[i]) {
212 src[i] = 0;
213 }
214 }
215 break;
216 case GL_SET:
217 for (i=0;i<n;i++) {
218 if (mask[i]) {
219 src[i] = ~0;
220 }
221 }
222 break;
223 case GL_COPY:
224 /* do nothing */
225 break;
226 case GL_COPY_INVERTED:
227 for (i=0;i<n;i++) {
228 if (mask[i]) {
229 src[i] = ~src[i];
230 }
231 }
232 break;
233 case GL_NOOP:
234 for (i=0;i<n;i++) {
235 if (mask[i]) {
236 src[i] = dest[i];
237 }
238 }
239 break;
240 case GL_INVERT:
241 for (i=0;i<n;i++) {
242 if (mask[i]) {
243 src[i] = ~dest[i];
244 }
245 }
246 break;
247 case GL_AND:
248 for (i=0;i<n;i++) {
249 if (mask[i]) {
250 src[i] &= dest[i];
251 }
252 }
253 break;
254 case GL_NAND:
255 for (i=0;i<n;i++) {
256 if (mask[i]) {
257 src[i] = ~(src[i] & dest[i]);
258 }
259 }
260 break;
261 case GL_OR:
262 for (i=0;i<n;i++) {
263 if (mask[i]) {
264 src[i]|= dest[i];
265 }
266 }
267 break;
268 case GL_NOR:
269 for (i=0;i<n;i++) {
270 if (mask[i]) {
271 src[i] = ~(src[i] | dest[i]);
272 }
273 }
274 break;
275 case GL_XOR:
276 for (i=0;i<n;i++) {
277 if (mask[i]) {
278 src[i] ^= dest[i];
279 }
280 }
281 break;
282 case GL_EQUIV:
283 for (i=0;i<n;i++) {
284 if (mask[i]) {
285 src[i] = ~(src[i] ^ dest[i]);
286 }
287 }
288 break;
289 case GL_AND_REVERSE:
290 for (i=0;i<n;i++) {
291 if (mask[i]) {
292 src[i] = src[i] & ~dest[i];
293 }
294 }
295 break;
296 case GL_AND_INVERTED:
297 for (i=0;i<n;i++) {
298 if (mask[i]) {
299 src[i] = ~src[i] & dest[i];
300 }
301 }
302 break;
303 case GL_OR_REVERSE:
304 for (i=0;i<n;i++) {
305 if (mask[i]) {
306 src[i] = src[i] | ~dest[i];
307 }
308 }
309 break;
310 case GL_OR_INVERTED:
311 for (i=0;i<n;i++) {
312 if (mask[i]) {
313 src[i] = ~src[i] | dest[i];
314 }
315 }
316 break;
317 default:
318 /* should never happen */
319 _mesa_problem(ctx, "Bad function in rgba_logicop");
320 }
321 }
322
323
324 /*
325 * As above, but operate on GLchan values
326 * Note: need to pass n = numPixels * 4.
327 */
328 static void
329 rgba_logicop_chan( const GLcontext *ctx, GLuint n, const GLubyte mask[],
330 GLchan srcPtr[], const GLchan destPtr[] )
331 {
332 #if CHAN_TYPE == GL_FLOAT
333 GLuint *src = (GLuint *) srcPtr;
334 const GLuint *dest = (const GLuint *) destPtr;
335 GLuint i;
336 ASSERT(sizeof(GLfloat) == sizeof(GLuint));
337 #else
338 GLchan *src = srcPtr;
339 const GLchan *dest = destPtr;
340 GLuint i;
341 #endif
342
343 switch (ctx->Color.LogicOp) {
344 case GL_CLEAR:
345 for (i=0;i<n;i++) {
346 if (mask[i]) {
347 src[i] = 0;
348 }
349 }
350 break;
351 case GL_SET:
352 for (i=0;i<n;i++) {
353 if (mask[i]) {
354 src[i] = ~0;
355 }
356 }
357 break;
358 case GL_COPY:
359 /* do nothing */
360 break;
361 case GL_COPY_INVERTED:
362 for (i=0;i<n;i++) {
363 if (mask[i]) {
364 src[i] = ~src[i];
365 }
366 }
367 break;
368 case GL_NOOP:
369 for (i=0;i<n;i++) {
370 if (mask[i]) {
371 src[i] = dest[i];
372 }
373 }
374 break;
375 case GL_INVERT:
376 for (i=0;i<n;i++) {
377 if (mask[i]) {
378 src[i] = ~dest[i];
379 }
380 }
381 break;
382 case GL_AND:
383 for (i=0;i<n;i++) {
384 if (mask[i]) {
385 src[i] &= dest[i];
386 }
387 }
388 break;
389 case GL_NAND:
390 for (i=0;i<n;i++) {
391 if (mask[i]) {
392 src[i] = ~(src[i] & dest[i]);
393 }
394 }
395 break;
396 case GL_OR:
397 for (i=0;i<n;i++) {
398 if (mask[i]) {
399 src[i]|= dest[i];
400 }
401 }
402 break;
403 case GL_NOR:
404 for (i=0;i<n;i++) {
405 if (mask[i]) {
406 src[i] = ~(src[i] | dest[i]);
407 }
408 }
409 break;
410 case GL_XOR:
411 for (i=0;i<n;i++) {
412 if (mask[i]) {
413 src[i] ^= dest[i];
414 }
415 }
416 break;
417 case GL_EQUIV:
418 for (i=0;i<n;i++) {
419 if (mask[i]) {
420 src[i] = ~(src[i] ^ dest[i]);
421 }
422 }
423 break;
424 case GL_AND_REVERSE:
425 for (i=0;i<n;i++) {
426 if (mask[i]) {
427 src[i] = src[i] & ~dest[i];
428 }
429 }
430 break;
431 case GL_AND_INVERTED:
432 for (i=0;i<n;i++) {
433 if (mask[i]) {
434 src[i] = ~src[i] & dest[i];
435 }
436 }
437 break;
438 case GL_OR_REVERSE:
439 for (i=0;i<n;i++) {
440 if (mask[i]) {
441 src[i] = src[i] | ~dest[i];
442 }
443 }
444 break;
445 case GL_OR_INVERTED:
446 for (i=0;i<n;i++) {
447 if (mask[i]) {
448 src[i] = ~src[i] | dest[i];
449 }
450 }
451 break;
452 default:
453 /* should never happen */
454 _mesa_problem(ctx, "Bad function in rgba_logicop");
455 }
456 }
457
458
459
460 /*
461 * Apply the current logic operator to a span of RGBA pixels.
462 * We can handle horizontal runs of pixels (spans) or arrays of x/y
463 * pixel coordinates.
464 */
465 void
466 _mesa_logicop_rgba_span( GLcontext *ctx, const struct sw_span *span,
467 GLchan rgba[][4] )
468 {
469 SWcontext *swrast = SWRAST_CONTEXT(ctx);
470 GLchan dest[MAX_WIDTH][4];
471
472 ASSERT(span->end < MAX_WIDTH);
473 ASSERT(span->arrayMask & SPAN_RGBA);
474
475 if (span->arrayMask & SPAN_XY) {
476 (*swrast->Driver.ReadRGBAPixels)(ctx, span->end,
477 span->array->x, span->array->y,
478 dest, span->array->mask);
479 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
480 _mesa_read_alpha_pixels(ctx, span->end,
481 span->array->x, span->array->y,
482 dest, span->array->mask);
483 }
484 }
485 else {
486 _mesa_read_rgba_span(ctx, ctx->DrawBuffer, span->end,
487 span->x, span->y, dest);
488 }
489
490 if (sizeof(GLchan) * 4 == sizeof(GLuint)) {
491 rgba_logicop_ui(ctx, span->end, span->array->mask,
492 (GLuint *) rgba, (const GLuint *) dest);
493 }
494 else {
495 rgba_logicop_chan(ctx, 4 * span->end, span->array->mask,
496 (GLchan *) rgba, (const GLchan *) dest);
497 }
498 }