xref: /reactos/dll/opengl/mesa/logic.c (revision 7eead935)
1 /* $Id: logic.c,v 1.7 1997/07/24 01:24:11 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version:  2.4
6  * Copyright (C) 1995-1997  Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: logic.c,v $
26  * Revision 1.7  1997/07/24 01:24:11  brianp
27  * changed precompiled header symbol from PCH to PC_HEADER
28  *
29  * Revision 1.6  1997/05/28 03:25:26  brianp
30  * added precompiled header (PCH) support
31  *
32  * Revision 1.5  1997/04/20 20:28:49  brianp
33  * replaced abort() with gl_problem()
34  *
35  * Revision 1.4  1997/03/04 18:56:57  brianp
36  * added #include <stdlib.h> for abort()
37  *
38  * Revision 1.3  1997/01/28 22:16:31  brianp
39  * added gl_logicop_rgba_span() and gl_logicop_rgba_pixels()
40  *
41  * Revision 1.2  1997/01/04 00:13:11  brianp
42  * was using ! instead of ~ to invert pixel bits (ugh!)
43  *
44  * Revision 1.1  1996/09/13 01:38:16  brianp
45  * Initial revision
46  *
47  */
48 
49 
50 #ifdef PC_HEADER
51 #include "all.h"
52 #else
53 #include <stdlib.h>
54 #include "alphabuf.h"
55 #include "context.h"
56 #include "dlist.h"
57 #include "logic.h"
58 #include "macros.h"
59 #include "pb.h"
60 #include "span.h"
61 #include "types.h"
62 #endif
63 
64 
65 
66 void gl_LogicOp( GLcontext *ctx, GLenum opcode )
67 {
68    if (INSIDE_BEGIN_END(ctx)) {
69       gl_error( ctx, GL_INVALID_OPERATION, "glLogicOp" );
70       return;
71    }
72    switch (opcode) {
73       case GL_CLEAR:
74       case GL_SET:
75       case GL_COPY:
76       case GL_COPY_INVERTED:
77       case GL_NOOP:
78       case GL_INVERT:
79       case GL_AND:
80       case GL_NAND:
81       case GL_OR:
82       case GL_NOR:
83       case GL_XOR:
84       case GL_EQUIV:
85       case GL_AND_REVERSE:
86       case GL_AND_INVERTED:
87       case GL_OR_REVERSE:
88       case GL_OR_INVERTED:
89          ctx->Color.LogicOp = opcode;
90          ctx->NewState |= NEW_RASTER_OPS;
91 	 return;
92       default:
93          gl_error( ctx, GL_INVALID_ENUM, "glLogicOp" );
94 	 return;
95    }
96 }
97 
98 
99 
100 
101 /*
102  * Apply the current logic operator to a span of CI pixels.  This is only
103  * used if the device driver can't do logic ops.
104  */
105 void gl_logicop_ci_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
106                          GLuint index[], GLubyte mask[] )
107 {
108    GLuint dest[MAX_WIDTH];
109    GLuint i;
110 
111    /* Read dest values from frame buffer */
112    (*ctx->Driver.ReadIndexSpan)( ctx, n, x, y, dest );
113 
114    switch (ctx->Color.LogicOp) {
115       case GL_CLEAR:
116          for (i=0;i<n;i++) {
117 	    if (mask[i]) {
118 	       index[i] = 0;
119 	    }
120 	 }
121 	 break;
122       case GL_SET:
123          for (i=0;i<n;i++) {
124 	    if (mask[i]) {
125 	       index[i] = 1;
126 	    }
127 	 }
128 	 break;
129       case GL_COPY:
130 	 /* do nothing */
131 	 break;
132       case GL_COPY_INVERTED:
133          for (i=0;i<n;i++) {
134 	    if (mask[i]) {
135 	       index[i] = ~index[i];
136 	    }
137 	 }
138 	 break;
139       case GL_NOOP:
140          for (i=0;i<n;i++) {
141 	    if (mask[i]) {
142 	       index[i] = dest[i];
143 	    }
144 	 }
145 	 break;
146       case GL_INVERT:
147          for (i=0;i<n;i++) {
148 	    if (mask[i]) {
149 	       index[i] = ~dest[i];
150 	    }
151 	 }
152 	 break;
153       case GL_AND:
154          for (i=0;i<n;i++) {
155 	    if (mask[i]) {
156 	       index[i] &= dest[i];
157 	    }
158 	 }
159 	 break;
160       case GL_NAND:
161          for (i=0;i<n;i++) {
162 	    if (mask[i]) {
163 	       index[i] = ~(index[i] & dest[i]);
164 	    }
165 	 }
166 	 break;
167       case GL_OR:
168          for (i=0;i<n;i++) {
169 	    if (mask[i]) {
170 	       index[i] |= dest[i];
171 	    }
172 	 }
173 	 break;
174       case GL_NOR:
175          for (i=0;i<n;i++) {
176 	    if (mask[i]) {
177 	       index[i] = ~(index[i] | dest[i]);
178 	    }
179 	 }
180 	 break;
181       case GL_XOR:
182          for (i=0;i<n;i++) {
183 	    if (mask[i]) {
184 	       index[i] ^= dest[i];
185 	    }
186 	 }
187 	 break;
188       case GL_EQUIV:
189          for (i=0;i<n;i++) {
190 	    if (mask[i]) {
191 	       index[i] = ~(index[i] ^ dest[i]);
192 	    }
193 	 }
194 	 break;
195       case GL_AND_REVERSE:
196          for (i=0;i<n;i++) {
197 	    if (mask[i]) {
198 	       index[i] = index[i] & ~dest[i];
199 	    }
200 	 }
201 	 break;
202       case GL_AND_INVERTED:
203          for (i=0;i<n;i++) {
204 	    if (mask[i]) {
205 	       index[i] = ~index[i] & dest[i];
206 	    }
207 	 }
208 	 break;
209       case GL_OR_REVERSE:
210          for (i=0;i<n;i++) {
211 	    if (mask[i]) {
212 	       index[i] = index[i] | ~dest[i];
213 	    }
214 	 }
215 	 break;
216       case GL_OR_INVERTED:
217          for (i=0;i<n;i++) {
218 	    if (mask[i]) {
219 	       index[i] = ~index[i] | dest[i];
220 	    }
221 	 }
222 	 break;
223       default:
224 	 gl_error( ctx, GL_INVALID_ENUM, "gl_logic error" );
225    }
226 }
227 
228 
229 
230 /*
231  * Apply the current logic operator to an array of CI pixels.  This is only
232  * used if the device driver can't do logic ops.
233  */
234 void gl_logicop_ci_pixels( GLcontext *ctx,
235                            GLuint n, const GLint x[], const GLint y[],
236                            GLuint index[], GLubyte mask[] )
237 {
238    GLuint dest[PB_SIZE];
239    GLuint i;
240 
241    /* Read dest values from frame buffer */
242    (*ctx->Driver.ReadIndexPixels)( ctx, n, x, y, dest, mask );
243 
244    switch (ctx->Color.LogicOp) {
245       case GL_CLEAR:
246          for (i=0;i<n;i++) {
247 	    if (mask[i]) {
248 	       index[i] = 0;
249 	    }
250 	 }
251 	 break;
252       case GL_SET:
253          for (i=0;i<n;i++) {
254 	    if (mask[i]) {
255 	       index[i] = 1;
256 	    }
257 	 }
258 	 break;
259       case GL_COPY:
260 	 /* do nothing */
261 	 break;
262       case GL_COPY_INVERTED:
263          for (i=0;i<n;i++) {
264 	    if (mask[i]) {
265 	       index[i] = ~index[i];
266 	    }
267 	 }
268 	 break;
269       case GL_NOOP:
270          for (i=0;i<n;i++) {
271 	    if (mask[i]) {
272 	       index[i] = dest[i];
273 	    }
274 	 }
275 	 break;
276       case GL_INVERT:
277          for (i=0;i<n;i++) {
278 	    if (mask[i]) {
279 	       index[i] = ~dest[i];
280 	    }
281 	 }
282 	 break;
283       case GL_AND:
284          for (i=0;i<n;i++) {
285 	    if (mask[i]) {
286 	       index[i] &= dest[i];
287 	    }
288 	 }
289 	 break;
290       case GL_NAND:
291          for (i=0;i<n;i++) {
292 	    if (mask[i]) {
293 	       index[i] = ~(index[i] & dest[i]);
294 	    }
295 	 }
296 	 break;
297       case GL_OR:
298          for (i=0;i<n;i++) {
299 	    if (mask[i]) {
300 	       index[i] |= dest[i];
301 	    }
302 	 }
303 	 break;
304       case GL_NOR:
305          for (i=0;i<n;i++) {
306 	    if (mask[i]) {
307 	       index[i] = ~(index[i] | dest[i]);
308 	    }
309 	 }
310 	 break;
311       case GL_XOR:
312          for (i=0;i<n;i++) {
313 	    if (mask[i]) {
314 	       index[i] ^= dest[i];
315 	    }
316 	 }
317 	 break;
318       case GL_EQUIV:
319          for (i=0;i<n;i++) {
320 	    if (mask[i]) {
321 	       index[i] = ~(index[i] ^ dest[i]);
322 	    }
323 	 }
324 	 break;
325       case GL_AND_REVERSE:
326          for (i=0;i<n;i++) {
327 	    if (mask[i]) {
328 	       index[i] = index[i] & ~dest[i];
329 	    }
330 	 }
331 	 break;
332       case GL_AND_INVERTED:
333          for (i=0;i<n;i++) {
334 	    if (mask[i]) {
335 	       index[i] = ~index[i] & dest[i];
336 	    }
337 	 }
338 	 break;
339       case GL_OR_REVERSE:
340          for (i=0;i<n;i++) {
341 	    if (mask[i]) {
342 	       index[i] = index[i] | ~dest[i];
343 	    }
344 	 }
345 	 break;
346       case GL_OR_INVERTED:
347          for (i=0;i<n;i++) {
348 	    if (mask[i]) {
349 	       index[i] = ~index[i] | dest[i];
350 	    }
351 	 }
352 	 break;
353       default:
354 	 gl_error( ctx, GL_INVALID_ENUM, "gl_logic_pixels error" );
355    }
356 }
357 
358 
359 
360 /*
361  * Apply the current logic operator to a span of RGBA pixels.  This is only
362  * used if the device driver can't do logic ops.
363  */
364 void gl_logicop_rgba_span( GLcontext *ctx,
365                            GLuint n, GLint x, GLint y,
366                            GLubyte red[], GLubyte green[],
367                            GLubyte blue[], GLubyte alpha[],
368                            GLubyte mask[] )
369 {
370    GLubyte rdest[MAX_WIDTH], gdest[MAX_WIDTH];
371    GLubyte bdest[MAX_WIDTH], adest[MAX_WIDTH];
372    GLuint i;
373 
374    /* Read span of current frame buffer pixels */
375    gl_read_color_span( ctx, n, x, y, rdest, gdest, bdest, adest );
376 
377    /* apply logic op */
378    switch (ctx->Color.LogicOp) {
379       case GL_CLEAR:
380          for (i=0;i<n;i++) {
381             if (mask[i]) {
382                red[i] = green[i] = blue[i] = alpha[i] = 0;
383             }
384          }
385          break;
386       case GL_SET:
387          {
388             GLubyte r = (GLint) ctx->Visual->RedScale;
389             GLubyte g = (GLint) ctx->Visual->GreenScale;
390             GLubyte b = (GLint) ctx->Visual->BlueScale;
391             GLubyte a = (GLint) ctx->Visual->AlphaScale;
392             for (i=0;i<n;i++) {
393                if (mask[i]) {
394                   red[i]   = r;
395                   green[i] = g;
396                   blue[i]  = b;
397                   alpha[i] = a;
398                }
399             }
400          }
401          break;
402       case GL_COPY:
403          /* do nothing */
404          break;
405       case GL_COPY_INVERTED:
406          for (i=0;i<n;i++) {
407             if (mask[i]) {
408                red[i]   = ~red[i];
409                green[i] = ~green[i];
410                blue[i]  = ~blue[i];
411                alpha[i] = ~alpha[i];
412             }
413          }
414          break;
415       case GL_NOOP:
416          for (i=0;i<n;i++) {
417             if (mask[i]) {
418                red[i]   = rdest[i];
419                green[i] = gdest[i];
420                blue[i]  = bdest[i];
421                alpha[i] = adest[i];
422             }
423          }
424          break;
425       case GL_INVERT:
426          for (i=0;i<n;i++) {
427             if (mask[i]) {
428                red[i]   = ~rdest[i];
429                green[i] = ~gdest[i];
430                blue[i]  = ~bdest[i];
431                alpha[i] = ~adest[i];
432             }
433          }
434          break;
435       case GL_AND:
436          for (i=0;i<n;i++) {
437             if (mask[i]) {
438                red[i]   &= rdest[i];
439                green[i] &= gdest[i];
440                blue[i]  &= bdest[i];
441                alpha[i] &= adest[i];
442             }
443          }
444          break;
445       case GL_NAND:
446          for (i=0;i<n;i++) {
447             if (mask[i]) {
448                red[i]   = ~(red[i]   & rdest[i]);
449                green[i] = ~(green[i] & gdest[i]);
450                blue[i]  = ~(blue[i]  & bdest[i]);
451                alpha[i] = ~(alpha[i] & adest[i]);
452             }
453          }
454          break;
455       case GL_OR:
456          for (i=0;i<n;i++) {
457             if (mask[i]) {
458                red[i]   |= rdest[i];
459                green[i] |= gdest[i];
460                blue[i]  |= bdest[i];
461                alpha[i] |= adest[i];
462             }
463          }
464          break;
465       case GL_NOR:
466          for (i=0;i<n;i++) {
467             if (mask[i]) {
468                red[i]   = ~(red[i]   | rdest[i]);
469                green[i] = ~(green[i] | gdest[i]);
470                blue[i]  = ~(blue[i]  | bdest[i]);
471                alpha[i] = ~(alpha[i] | adest[i]);
472             }
473          }
474          break;
475       case GL_XOR:
476          for (i=0;i<n;i++) {
477             if (mask[i]) {
478                red[i]   ^= rdest[i];
479                green[i] ^= gdest[i];
480                blue[i]  ^= bdest[i];
481                alpha[i] ^= adest[i];
482             }
483          }
484          break;
485       case GL_EQUIV:
486          for (i=0;i<n;i++) {
487             if (mask[i]) {
488                red[i]   = ~(red[i]   ^ rdest[i]);
489                green[i] = ~(green[i] ^ gdest[i]);
490                blue[i]  = ~(blue[i]  ^ bdest[i]);
491                alpha[i] = ~(alpha[i] ^ adest[i]);
492             }
493          }
494          break;
495       case GL_AND_REVERSE:
496          for (i=0;i<n;i++) {
497             if (mask[i]) {
498                red[i]   = red[i]   & ~rdest[i];
499                green[i] = green[i] & ~gdest[i];
500                blue[i]  = blue[i]  & ~bdest[i];
501                alpha[i] = alpha[i] & ~adest[i];
502             }
503          }
504          break;
505       case GL_AND_INVERTED:
506          for (i=0;i<n;i++) {
507             if (mask[i]) {
508                red[i]   = ~red[i]   & rdest[i];
509                green[i] = ~green[i] & gdest[i];
510                blue[i]  = ~blue[i]  & bdest[i];
511                alpha[i] = ~alpha[i] & adest[i];
512             }
513          }
514          break;
515       case GL_OR_REVERSE:
516          for (i=0;i<n;i++) {
517             if (mask[i]) {
518                red[i]   = red[i]   | ~rdest[i];
519                green[i] = green[i] | ~gdest[i];
520                blue[i]  = blue[i]  | ~bdest[i];
521                alpha[i] = alpha[i] | ~adest[i];
522             }
523          }
524          break;
525       case GL_OR_INVERTED:
526          for (i=0;i<n;i++) {
527             if (mask[i]) {
528                red[i]   = ~red[i]   | rdest[i];
529                green[i] = ~green[i] | gdest[i];
530                blue[i]  = ~blue[i]  | bdest[i];
531                alpha[i] = ~alpha[i] | adest[i];
532             }
533          }
534          break;
535       default:
536          /* should never happen */
537          gl_problem(ctx, "Bad function in gl_logicop_rgba_span");
538          return;
539    }
540 }
541 
542 
543 
544 /*
545  * Apply the current logic operator to an array of RGBA pixels.  This is only
546  * used if the device driver can't do logic ops.
547  */
548 void gl_logicop_rgba_pixels( GLcontext *ctx,
549                              GLuint n, const GLint x[], const GLint y[],
550                              GLubyte red[], GLubyte green[],
551                              GLubyte blue[], GLubyte alpha[],
552                              GLubyte mask[] )
553 {
554    GLubyte rdest[PB_SIZE], gdest[PB_SIZE], bdest[PB_SIZE], adest[PB_SIZE];
555    GLuint i;
556 
557    /* Read pixels from current color buffer */
558    (*ctx->Driver.ReadColorPixels)( ctx, n, x, y, rdest, gdest, bdest, adest, mask );
559    if (ctx->RasterMask & ALPHABUF_BIT) {
560       gl_read_alpha_pixels( ctx, n, x, y, adest, mask );
561    }
562 
563    /* apply logic op */
564    switch (ctx->Color.LogicOp) {
565       case GL_CLEAR:
566          for (i=0;i<n;i++) {
567             if (mask[i]) {
568                red[i] = green[i] = blue[i] = alpha[i] = 0;
569             }
570          }
571          break;
572       case GL_SET:
573          {
574             GLubyte r = (GLint) ctx->Visual->RedScale;
575             GLubyte g = (GLint) ctx->Visual->GreenScale;
576             GLubyte b = (GLint) ctx->Visual->BlueScale;
577             GLubyte a = (GLint) ctx->Visual->AlphaScale;
578             for (i=0;i<n;i++) {
579                if (mask[i]) {
580                   red[i]   = r;
581                   green[i] = g;
582                   blue[i]  = b;
583                   alpha[i] = a;
584                }
585             }
586          }
587          break;
588       case GL_COPY:
589          /* do nothing */
590          break;
591       case GL_COPY_INVERTED:
592          for (i=0;i<n;i++) {
593             if (mask[i]) {
594                red[i]   = ~red[i];
595                green[i] = ~green[i];
596                blue[i]  = ~blue[i];
597                alpha[i] = ~alpha[i];
598             }
599          }
600          break;
601       case GL_NOOP:
602          for (i=0;i<n;i++) {
603             if (mask[i]) {
604                red[i]   = rdest[i];
605                green[i] = gdest[i];
606                blue[i]  = bdest[i];
607                alpha[i] = adest[i];
608             }
609          }
610          break;
611       case GL_INVERT:
612          for (i=0;i<n;i++) {
613             if (mask[i]) {
614                red[i]   = ~rdest[i];
615                green[i] = ~gdest[i];
616                blue[i]  = ~bdest[i];
617                alpha[i] = ~adest[i];
618             }
619          }
620          break;
621       case GL_AND:
622          for (i=0;i<n;i++) {
623             if (mask[i]) {
624                red[i]   &= rdest[i];
625                green[i] &= gdest[i];
626                blue[i]  &= bdest[i];
627                alpha[i] &= adest[i];
628             }
629          }
630          break;
631       case GL_NAND:
632          for (i=0;i<n;i++) {
633             if (mask[i]) {
634                red[i]   = ~(red[i]   & rdest[i]);
635                green[i] = ~(green[i] & gdest[i]);
636                blue[i]  = ~(blue[i]  & bdest[i]);
637                alpha[i] = ~(alpha[i] & adest[i]);
638             }
639          }
640          break;
641       case GL_OR:
642          for (i=0;i<n;i++) {
643             if (mask[i]) {
644                red[i]   |= rdest[i];
645                green[i] |= gdest[i];
646                blue[i]  |= bdest[i];
647                alpha[i] |= adest[i];
648             }
649          }
650          break;
651       case GL_NOR:
652          for (i=0;i<n;i++) {
653             if (mask[i]) {
654                red[i]   = ~(red[i]   | rdest[i]);
655                green[i] = ~(green[i] | gdest[i]);
656                blue[i]  = ~(blue[i]  | bdest[i]);
657                alpha[i] = ~(alpha[i] | adest[i]);
658             }
659          }
660          break;
661       case GL_XOR:
662          for (i=0;i<n;i++) {
663             if (mask[i]) {
664                red[i]   ^= rdest[i];
665                green[i] ^= gdest[i];
666                blue[i]  ^= bdest[i];
667                alpha[i] ^= adest[i];
668             }
669          }
670          break;
671       case GL_EQUIV:
672          for (i=0;i<n;i++) {
673             if (mask[i]) {
674                red[i]   = ~(red[i]   ^ rdest[i]);
675                green[i] = ~(green[i] ^ gdest[i]);
676                blue[i]  = ~(blue[i]  ^ bdest[i]);
677                alpha[i] = ~(alpha[i] ^ adest[i]);
678             }
679          }
680          break;
681       case GL_AND_REVERSE:
682          for (i=0;i<n;i++) {
683             if (mask[i]) {
684                red[i]   = red[i]   & ~rdest[i];
685                green[i] = green[i] & ~gdest[i];
686                blue[i]  = blue[i]  & ~bdest[i];
687                alpha[i] = alpha[i] & ~adest[i];
688             }
689          }
690          break;
691       case GL_AND_INVERTED:
692          for (i=0;i<n;i++) {
693             if (mask[i]) {
694                red[i]   = ~red[i]   & rdest[i];
695                green[i] = ~green[i] & gdest[i];
696                blue[i]  = ~blue[i]  & bdest[i];
697                alpha[i] = ~alpha[i] & adest[i];
698             }
699          }
700          break;
701       case GL_OR_REVERSE:
702          for (i=0;i<n;i++) {
703             if (mask[i]) {
704                red[i]   = red[i]   | ~rdest[i];
705                green[i] = green[i] | ~gdest[i];
706                blue[i]  = blue[i]  | ~bdest[i];
707                alpha[i] = alpha[i] | ~adest[i];
708             }
709          }
710          break;
711       case GL_OR_INVERTED:
712          for (i=0;i<n;i++) {
713             if (mask[i]) {
714                red[i]   = ~red[i]   | rdest[i];
715                green[i] = ~green[i] | gdest[i];
716                blue[i]  = ~blue[i]  | bdest[i];
717                alpha[i] = ~alpha[i] | adest[i];
718             }
719          }
720          break;
721       default:
722          /* should never happen */
723          gl_problem(ctx, "Bad function in gl_logicop_rgba_pixels");
724          return;
725    }
726 }
727