Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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