s_logic.c revision 8f28f4850bbf4f32e84f25ee1a8d72b16b8a41d1
1/* $Id: s_logic.c,v 1.3 2001/02/13 23:50:25 brianp Exp $ */
2
3/*
4 * Mesa 3-D graphics library
5 * Version:  3.5
6 *
7 * Copyright (C) 1999-2000  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 */
43static 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	 gl_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 */
168void
169_mesa_logicop_ci_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
170                       GLuint index[], const GLubyte mask[] )
171{
172   GLuint dest[MAX_WIDTH];
173   /* Read dest values from frame buffer */
174   (*ctx->Driver.ReadCI32Span)( ctx, n, x, y, dest );
175   index_logicop( ctx, n, index, dest, mask );
176}
177
178
179
180/*
181 * Apply the current logic operator to an array of CI pixels.  This is only
182 * used if the device driver can't do logic ops.
183 */
184void
185_mesa_logicop_ci_pixels( GLcontext *ctx,
186                         GLuint n, const GLint x[], const GLint y[],
187                         GLuint index[], const GLubyte mask[] )
188{
189   GLuint dest[PB_SIZE];
190   /* Read dest values from frame buffer */
191   (*ctx->Driver.ReadCI32Pixels)( ctx, n, x, y, dest, mask );
192   index_logicop( ctx, n, index, dest, mask );
193}
194
195
196
197/*
198 * Apply logic operator to rgba pixels.
199 * Input:  ctx - the context
200 *         n - number of pixels
201 *         mask - pixel mask array
202 * In/Out:  src - incoming pixels which will be modified
203 * Input:  dest - frame buffer values
204 *
205 * Note:  Since the R, G, B, and A channels are all treated the same we
206 * process them as 4-byte GLuints instead of four GLubytes.
207 */
208static void rgba_logicop( const GLcontext *ctx, GLuint n,
209                          const GLubyte mask[],
210                          GLuint src[], const GLuint dest[] )
211{
212   GLuint i;
213   switch (ctx->Color.LogicOp) {
214      case GL_CLEAR:
215         for (i=0;i<n;i++) {
216            if (mask[i]) {
217               src[i] = 0;
218            }
219         }
220         break;
221      case GL_SET:
222         for (i=0;i<n;i++) {
223            if (mask[i]) {
224               src[i] = ~0;
225            }
226         }
227         break;
228      case GL_COPY:
229         /* do nothing */
230         break;
231      case GL_COPY_INVERTED:
232         for (i=0;i<n;i++) {
233            if (mask[i]) {
234               src[i] = ~src[i];
235            }
236         }
237         break;
238      case GL_NOOP:
239         for (i=0;i<n;i++) {
240            if (mask[i]) {
241               src[i] = dest[i];
242            }
243         }
244         break;
245      case GL_INVERT:
246         for (i=0;i<n;i++) {
247            if (mask[i]) {
248               src[i] = ~dest[i];
249            }
250         }
251         break;
252      case GL_AND:
253         for (i=0;i<n;i++) {
254            if (mask[i]) {
255               src[i] &= dest[i];
256            }
257         }
258         break;
259      case GL_NAND:
260         for (i=0;i<n;i++) {
261            if (mask[i]) {
262               src[i] = ~(src[i] & src[i]);
263            }
264         }
265         break;
266      case GL_OR:
267         for (i=0;i<n;i++) {
268            if (mask[i]) {
269               src[i]|= dest[i];
270            }
271         }
272         break;
273      case GL_NOR:
274         for (i=0;i<n;i++) {
275            if (mask[i]) {
276               src[i] = ~(src[i] | dest[i]);
277            }
278         }
279         break;
280      case GL_XOR:
281         for (i=0;i<n;i++) {
282            if (mask[i]) {
283               src[i] ^= dest[i];
284            }
285         }
286         break;
287      case GL_EQUIV:
288         for (i=0;i<n;i++) {
289            if (mask[i]) {
290               src[i] = ~(src[i] ^ dest[i]);
291            }
292         }
293         break;
294      case GL_AND_REVERSE:
295         for (i=0;i<n;i++) {
296            if (mask[i]) {
297               src[i] = src[i] & ~dest[i];
298            }
299         }
300         break;
301      case GL_AND_INVERTED:
302         for (i=0;i<n;i++) {
303            if (mask[i]) {
304               src[i] = ~src[i] & dest[i];
305            }
306         }
307         break;
308      case GL_OR_REVERSE:
309         for (i=0;i<n;i++) {
310            if (mask[i]) {
311               src[i] = src[i] | ~dest[i];
312            }
313         }
314         break;
315      case GL_OR_INVERTED:
316         for (i=0;i<n;i++) {
317            if (mask[i]) {
318               src[i] = ~src[i] | dest[i];
319            }
320         }
321         break;
322      default:
323         /* should never happen */
324         gl_problem(ctx, "Bad function in rgba_logicop");
325   }
326}
327
328
329
330/*
331 * Apply the current logic operator to a span of RGBA pixels.
332 * This is only used if the device driver can't do logic ops.
333 */
334void
335_mesa_logicop_rgba_span( GLcontext *ctx,
336                         GLuint n, GLint x, GLint y,
337                         GLchan rgba[][4], const GLubyte mask[] )
338{
339   GLchan dest[MAX_WIDTH][4];
340   gl_read_rgba_span( ctx, ctx->DrawBuffer, n, x, y, dest );
341   rgba_logicop( ctx, n, mask, (GLuint *) rgba, (const GLuint *) dest );
342}
343
344
345
346/*
347 * Apply the current logic operator to an array of RGBA pixels.
348 * This is only used if the device driver can't do logic ops.
349 */
350void
351_mesa_logicop_rgba_pixels( GLcontext *ctx,
352                           GLuint n, const GLint x[], const GLint y[],
353                           GLchan rgba[][4], const GLubyte mask[] )
354{
355   GLchan dest[PB_SIZE][4];
356   (*ctx->Driver.ReadRGBAPixels)( ctx, n, x, y, dest, mask );
357   if (SWRAST_CONTEXT(ctx)->_RasterMask & ALPHABUF_BIT) {
358      _mesa_read_alpha_pixels( ctx, n, x, y, dest, mask );
359   }
360   rgba_logicop( ctx, n, mask, (GLuint *) rgba, (const GLuint *) dest );
361}
362