s_logic.c revision 5ec5c6b22262e83706f8b1c42d9e6b5b432a7f8b
1/*
2 * Mesa 3-D graphics library
3 * Version:  6.3
4 *
5 * Copyright (C) 1999-2005  Brian Paul   All Rights Reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a
8 * copy of this software and associated documentation files (the "Software"),
9 * to deal in the Software without restriction, including without limitation
10 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 * and/or sell copies of the Software, and to permit persons to whom the
12 * Software is furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
20 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
21 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24
25
26#include "glheader.h"
27#include "context.h"
28#include "imports.h"
29#include "macros.h"
30
31#include "s_context.h"
32#include "s_logic.h"
33#include "s_span.h"
34
35
36#define LOGIC_OP_LOOP(MODE)			\
37do {						\
38   GLuint i;					\
39   switch (MODE) {				\
40      case GL_CLEAR:				\
41         for (i = 0; i < n; i++) {		\
42	    if (mask[i]) {			\
43	       src[i] = 0;			\
44	    }					\
45	 }					\
46	 break;					\
47      case GL_SET:				\
48         for (i = 0; i < n; i++) {		\
49	    if (mask[i]) {			\
50	       src[i] = ~0;			\
51	    }					\
52	 }					\
53	 break;					\
54      case GL_COPY:				\
55	 /* do nothing */			\
56	 break;					\
57      case GL_COPY_INVERTED:			\
58         for (i = 0; i < n; i++) {		\
59	    if (mask[i]) {			\
60	       src[i] = ~src[i];		\
61	    }					\
62	 }					\
63	 break;					\
64      case GL_NOOP:				\
65         for (i = 0; i < n; i++) {		\
66	    if (mask[i]) {			\
67	       src[i] = dest[i];		\
68	    }					\
69	 }					\
70	 break;					\
71      case GL_INVERT:				\
72         for (i = 0; i < n; i++) {		\
73	    if (mask[i]) {			\
74	       src[i] = ~dest[i];		\
75	    }					\
76	 }					\
77	 break;					\
78      case GL_AND:				\
79         for (i = 0; i < n; i++) {		\
80	    if (mask[i]) {			\
81	       src[i] &= dest[i];		\
82	    }					\
83	 }					\
84	 break;					\
85      case GL_NAND:				\
86         for (i = 0; i < n; i++) {		\
87	    if (mask[i]) {			\
88	       src[i] = ~(src[i] & dest[i]);	\
89	    }					\
90	 }					\
91	 break;					\
92      case GL_OR:				\
93         for (i = 0; i < n; i++) {		\
94	    if (mask[i]) {			\
95	       src[i] |= dest[i];		\
96	    }					\
97	 }					\
98	 break;					\
99      case GL_NOR:				\
100         for (i = 0; i < n; i++) {		\
101	    if (mask[i]) {			\
102	       src[i] = ~(src[i] | dest[i]);	\
103	    }					\
104	 }					\
105	 break;					\
106      case GL_XOR:				\
107         for (i = 0; i < n; i++) {		\
108	    if (mask[i]) {			\
109	       src[i] ^= dest[i];		\
110	    }					\
111	 }					\
112	 break;					\
113      case GL_EQUIV:				\
114         for (i = 0; i < n; i++) {		\
115	    if (mask[i]) {			\
116	       src[i] = ~(src[i] ^ dest[i]);	\
117	    }					\
118	 }					\
119	 break;					\
120      case GL_AND_REVERSE:			\
121         for (i = 0; i < n; i++) {		\
122	    if (mask[i]) {			\
123	       src[i] = src[i] & ~dest[i];	\
124	    }					\
125	 }					\
126	 break;					\
127      case GL_AND_INVERTED:			\
128         for (i = 0; i < n; i++) {		\
129	    if (mask[i]) {			\
130	       src[i] = ~src[i] & dest[i];	\
131	    }					\
132	 }					\
133	 break;					\
134      case GL_OR_REVERSE:			\
135         for (i = 0; i < n; i++) {		\
136	    if (mask[i]) {			\
137	       src[i] = src[i] | ~dest[i];	\
138	    }					\
139	 }					\
140	 break;					\
141      case GL_OR_INVERTED:			\
142         for (i = 0; i < n; i++) {		\
143	    if (mask[i]) {			\
144	       src[i] = ~src[i] | dest[i];	\
145	    }					\
146	 }					\
147	 break;					\
148      default:					\
149	 _mesa_problem(ctx, "bad logicop mode");\
150   }						\
151} while (0)
152
153
154
155static void
156logicop_ubyte(GLcontext *ctx, GLuint n, GLubyte src[], const GLubyte dest[],
157              const GLubyte mask[])
158{
159   LOGIC_OP_LOOP(ctx->Color.LogicOp);
160}
161
162
163static void
164logicop_ushort(GLcontext *ctx, GLuint n, GLushort src[], const GLushort dest[],
165               const GLubyte mask[])
166{
167   LOGIC_OP_LOOP(ctx->Color.LogicOp);
168}
169
170
171static void
172logicop_uint(GLcontext *ctx, GLuint n, GLuint src[], const GLuint dest[],
173             const GLubyte mask[])
174{
175   LOGIC_OP_LOOP(ctx->Color.LogicOp);
176}
177
178
179
180/*
181 * Apply the current logic operator to a span of CI pixels.  This is only
182 * used if the device driver can't do logic ops.
183 */
184void
185_swrast_logicop_ci_span(GLcontext *ctx, struct gl_renderbuffer *rb,
186                        const struct sw_span *span, GLuint index[])
187{
188   GLuint dest[MAX_WIDTH];
189
190   ASSERT(span->end < MAX_WIDTH);
191   ASSERT(rb->DataType == GL_UNSIGNED_INT);
192
193   /* Read dest values from frame buffer */
194   if (span->arrayMask & SPAN_XY) {
195      rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y, dest);
196   }
197   else {
198      rb->GetRow(ctx, rb, span->end, span->x, span->y, dest);
199   }
200
201   logicop_uint(ctx, span->end, index, dest, span->array->mask);
202}
203
204
205/**
206 * Apply the current logic operator to a span of RGBA pixels.
207 * We can handle horizontal runs of pixels (spans) or arrays of x/y
208 * pixel coordinates.
209 */
210void
211_swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
212                          const struct sw_span *span, GLchan rgba[][4])
213{
214   GLchan dest[MAX_WIDTH][4];
215
216   ASSERT(span->end < MAX_WIDTH);
217   ASSERT(span->arrayMask & SPAN_RGBA);
218   ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
219
220   if (span->arrayMask & SPAN_XY) {
221      rb->GetValues(ctx, rb, span->end, span->array->x, span->array->y, dest);
222   }
223   else {
224      _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y, dest);
225   }
226
227   /* NEW_RENDERBUFFER: XXX make this a runtime test */
228#if CHAN_TYPE == GL_UNSIGNED_BYTE
229   /* treat 4*GLubyte as GLuint */
230   logicop_uint(ctx, span->end, (GLuint *) rgba,
231                (const GLuint *) dest, span->array->mask);
232#elif CHAN_TYPE == GL_UNSIGNED_SHORT
233   logicop_ushort(ctx, 4 * span->end, (GLushort *) rgba,
234                  (const GLushort *) dest, span->array->mask);
235#elif CHAN_TYPE == GL_FLOAT
236   logicop_uint(ctx, 4 * span->end, (GLuint *) rgba,
237                (const GLuint *) dest, span->array->mask);
238#endif
239   (void) logicop_ubyte;
240   (void) logicop_ushort;
241   (void) logicop_uint;
242}
243