assorted changes for supporting GLfloat color channels (not done)
[mesa.git] / src / mesa / swrast / s_logic.c
1 /* $Id: s_logic.c,v 1.8 2001/07/13 20:07:37 brianp Exp $ */
2
3 /*
4 * Mesa 3-D graphics library
5 * Version: 3.5
6 *
7 * Copyright (C) 1999-2001 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 index_logicop( GLcontext *ctx, GLuint n,
44 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, GLuint n, GLint x, GLint y,
170 GLuint index[], const GLubyte mask[] )
171 {
172 SWcontext *swrast = SWRAST_CONTEXT(ctx);
173 GLuint dest[MAX_WIDTH];
174 /* Read dest values from frame buffer */
175 (*swrast->Driver.ReadCI32Span)( ctx, n, x, y, dest );
176 index_logicop( ctx, n, index, dest, mask );
177 }
178
179
180
181 /*
182 * Apply the current logic operator to an array of CI pixels. This is only
183 * used if the device driver can't do logic ops.
184 */
185 void
186 _mesa_logicop_ci_pixels( GLcontext *ctx,
187 GLuint n, const GLint x[], const GLint y[],
188 GLuint index[], const GLubyte mask[] )
189 {
190 SWcontext *swrast = SWRAST_CONTEXT(ctx);
191 GLuint dest[PB_SIZE];
192 /* Read dest values from frame buffer */
193 (*swrast->Driver.ReadCI32Pixels)( ctx, n, x, y, dest, mask );
194 index_logicop( ctx, n, index, dest, mask );
195 }
196
197
198
199 /*
200 * Apply logic operator to rgba pixels.
201 * Input: ctx - the context
202 * n - number of pixels
203 * mask - pixel mask array
204 * In/Out: src - incoming pixels which will be modified
205 * Input: dest - frame buffer values
206 *
207 * Note: Since the R, G, B, and A channels are all treated the same we
208 * process them as 4-byte GLuints instead of four GLubytes.
209 */
210 static void rgba_logicop_ui( const GLcontext *ctx, GLuint n,
211 const GLubyte mask[],
212 GLuint src[], const GLuint dest[] )
213 {
214 GLuint i;
215 switch (ctx->Color.LogicOp) {
216 case GL_CLEAR:
217 for (i=0;i<n;i++) {
218 if (mask[i]) {
219 src[i] = 0;
220 }
221 }
222 break;
223 case GL_SET:
224 for (i=0;i<n;i++) {
225 if (mask[i]) {
226 src[i] = ~0;
227 }
228 }
229 break;
230 case GL_COPY:
231 /* do nothing */
232 break;
233 case GL_COPY_INVERTED:
234 for (i=0;i<n;i++) {
235 if (mask[i]) {
236 src[i] = ~src[i];
237 }
238 }
239 break;
240 case GL_NOOP:
241 for (i=0;i<n;i++) {
242 if (mask[i]) {
243 src[i] = dest[i];
244 }
245 }
246 break;
247 case GL_INVERT:
248 for (i=0;i<n;i++) {
249 if (mask[i]) {
250 src[i] = ~dest[i];
251 }
252 }
253 break;
254 case GL_AND:
255 for (i=0;i<n;i++) {
256 if (mask[i]) {
257 src[i] &= dest[i];
258 }
259 }
260 break;
261 case GL_NAND:
262 for (i=0;i<n;i++) {
263 if (mask[i]) {
264 src[i] = ~(src[i] & dest[i]);
265 }
266 }
267 break;
268 case GL_OR:
269 for (i=0;i<n;i++) {
270 if (mask[i]) {
271 src[i]|= dest[i];
272 }
273 }
274 break;
275 case GL_NOR:
276 for (i=0;i<n;i++) {
277 if (mask[i]) {
278 src[i] = ~(src[i] | dest[i]);
279 }
280 }
281 break;
282 case GL_XOR:
283 for (i=0;i<n;i++) {
284 if (mask[i]) {
285 src[i] ^= dest[i];
286 }
287 }
288 break;
289 case GL_EQUIV:
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_REVERSE:
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_AND_INVERTED:
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_REVERSE:
311 for (i=0;i<n;i++) {
312 if (mask[i]) {
313 src[i] = src[i] | ~dest[i];
314 }
315 }
316 break;
317 case GL_OR_INVERTED:
318 for (i=0;i<n;i++) {
319 if (mask[i]) {
320 src[i] = ~src[i] | dest[i];
321 }
322 }
323 break;
324 default:
325 /* should never happen */
326 _mesa_problem(ctx, "Bad function in rgba_logicop");
327 }
328 }
329
330
331 /*
332 * As above, but operate on GLchan values
333 * Note: need to pass n = numPixels * 4.
334 */
335 static void rgba_logicop_chan( const GLcontext *ctx, GLuint n,
336 const GLubyte mask[],
337 GLchan srcPtr[], const GLchan destPtr[] )
338 {
339 #if CHAN_TYPE == GL_FLOAT
340 GLuint *src = (GLuint *) srcPtr;
341 const GLuint *dest = (const GLuint *) destPtr;
342 GLuint i;
343 ASSERT(sizeof(GLfloat) == sizeof(GLuint));
344 #else
345 GLchan *src = srcPtr;
346 const GLchan *dest = destPtr;
347 GLuint i;
348 #endif
349
350 switch (ctx->Color.LogicOp) {
351 case GL_CLEAR:
352 for (i=0;i<n;i++) {
353 if (mask[i]) {
354 src[i] = 0;
355 }
356 }
357 break;
358 case GL_SET:
359 for (i=0;i<n;i++) {
360 if (mask[i]) {
361 src[i] = ~0;
362 }
363 }
364 break;
365 case GL_COPY:
366 /* do nothing */
367 break;
368 case GL_COPY_INVERTED:
369 for (i=0;i<n;i++) {
370 if (mask[i]) {
371 src[i] = ~src[i];
372 }
373 }
374 break;
375 case GL_NOOP:
376 for (i=0;i<n;i++) {
377 if (mask[i]) {
378 src[i] = dest[i];
379 }
380 }
381 break;
382 case GL_INVERT:
383 for (i=0;i<n;i++) {
384 if (mask[i]) {
385 src[i] = ~dest[i];
386 }
387 }
388 break;
389 case GL_AND:
390 for (i=0;i<n;i++) {
391 if (mask[i]) {
392 src[i] &= dest[i];
393 }
394 }
395 break;
396 case GL_NAND:
397 for (i=0;i<n;i++) {
398 if (mask[i]) {
399 src[i] = ~(src[i] & dest[i]);
400 }
401 }
402 break;
403 case GL_OR:
404 for (i=0;i<n;i++) {
405 if (mask[i]) {
406 src[i]|= dest[i];
407 }
408 }
409 break;
410 case GL_NOR:
411 for (i=0;i<n;i++) {
412 if (mask[i]) {
413 src[i] = ~(src[i] | dest[i]);
414 }
415 }
416 break;
417 case GL_XOR:
418 for (i=0;i<n;i++) {
419 if (mask[i]) {
420 src[i] ^= dest[i];
421 }
422 }
423 break;
424 case GL_EQUIV:
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_REVERSE:
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_AND_INVERTED:
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_REVERSE:
446 for (i=0;i<n;i++) {
447 if (mask[i]) {
448 src[i] = src[i] | ~dest[i];
449 }
450 }
451 break;
452 case GL_OR_INVERTED:
453 for (i=0;i<n;i++) {
454 if (mask[i]) {
455 src[i] = ~src[i] | dest[i];
456 }
457 }
458 break;
459 default:
460 /* should never happen */
461 _mesa_problem(ctx, "Bad function in rgba_logicop");
462 }
463 }
464
465
466
467 /*
468 * Apply the current logic operator to a span of RGBA pixels.
469 * This is only used if the device driver can't do logic ops.
470 */
471 void
472 _mesa_logicop_rgba_span( GLcontext *ctx,
473 GLuint n, GLint x, GLint y,
474 GLchan rgba[][4], const GLubyte mask[] )
475 {
476 GLchan dest[MAX_WIDTH][4];
477 _mesa_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest );
478 if (sizeof(GLchan) * 4 == sizeof(GLuint)) {
479 rgba_logicop_ui(ctx, n, mask, (GLuint *) rgba, (const GLuint *) dest);
480 }
481 else {
482 rgba_logicop_chan(ctx, 4 * n, mask,
483 (GLchan *) rgba, (const GLchan *) dest);
484 }
485 }
486
487
488
489 /*
490 * Apply the current logic operator to an array of RGBA pixels.
491 * This is only used if the device driver can't do logic ops.
492 */
493 void
494 _mesa_logicop_rgba_pixels( GLcontext *ctx,
495 GLuint n, const GLint x[], const GLint y[],
496 GLchan rgba[][4], const GLubyte mask[] )
497 {
498 SWcontext *swrast = SWRAST_CONTEXT(ctx);
499 GLchan dest[PB_SIZE][4];
500 (*swrast->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
501 if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
502 _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask );
503 }
504 if (sizeof(GLchan) * 4 == sizeof(GLuint)) {
505 rgba_logicop_ui(ctx, n, mask, (GLuint *) rgba, (const GLuint *) dest);
506 }
507 else {
508 rgba_logicop_chan(ctx, 4 * n, mask,
509 (GLchan *) rgba, (const GLchan *) dest);
510 }
511 }