fixes for CHAN_BITS!=8
[mesa.git] / src / mesa / swrast / s_logic.c
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) \
37 do { \
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
155 static void
156 logicop_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
163 static void
164 logicop_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
171 static void
172 logicop_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 */
184 void
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 _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
196 dest, sizeof(GLuint));
197 }
198 else {
199 rb->GetRow(ctx, rb, span->end, span->x, span->y, dest);
200 }
201
202 logicop_uint(ctx, span->end, index, dest, span->array->mask);
203 }
204
205
206 /**
207 * Apply the current logic operator to a span of RGBA pixels.
208 * We can handle horizontal runs of pixels (spans) or arrays of x/y
209 * pixel coordinates.
210 */
211 void
212 _swrast_logicop_rgba_span(GLcontext *ctx, struct gl_renderbuffer *rb,
213 const struct sw_span *span, GLchan rgba[][4])
214 {
215 GLchan dest[MAX_WIDTH][4];
216
217 ASSERT(span->end < MAX_WIDTH);
218 ASSERT(span->arrayMask & SPAN_RGBA);
219 ASSERT(rb->DataType == CHAN_TYPE);
220
221 if (span->arrayMask & SPAN_XY) {
222 _swrast_get_values(ctx, rb, span->end, span->array->x, span->array->y,
223 dest, 4 * sizeof(GLchan));
224 }
225 else {
226 _swrast_read_rgba_span(ctx, rb, span->end, span->x, span->y, dest);
227 }
228
229 /* XXX make this a runtime test */
230 #if CHAN_TYPE == GL_UNSIGNED_BYTE
231 /* treat 4*GLubyte as GLuint */
232 logicop_uint(ctx, span->end, (GLuint *) rgba,
233 (const GLuint *) dest, span->array->mask);
234 #elif CHAN_TYPE == GL_UNSIGNED_SHORT
235 logicop_ushort(ctx, 4 * span->end, (GLushort *) rgba,
236 (const GLushort *) dest, span->array->mask);
237 #elif CHAN_TYPE == GL_FLOAT
238 logicop_uint(ctx, 4 * span->end, (GLuint *) rgba,
239 (const GLuint *) dest, span->array->mask);
240 #endif
241 (void) logicop_ubyte;
242 (void) logicop_ushort;
243 (void) logicop_uint;
244 }