~ubuntu-branches/ubuntu/quantal/mesa-glw/quantal

« back to all changes in this revision

Viewing changes to src/mesa/swrast/s_stencil.c

  • Committer: Bazaar Package Importer
  • Author(s): Morten Kjeldgaard
  • Date: 2008-05-06 16:19:15 UTC
  • Revision ID: james.westby@ubuntu.com-20080506161915-uynz7nftmfixu6bq
Tags: upstream-7.0.3
ImportĀ upstreamĀ versionĀ 7.0.3

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Mesa 3-D graphics library
 
3
 * Version:  6.5
 
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
 
 
30
#include "s_context.h"
 
31
#include "s_depth.h"
 
32
#include "s_stencil.h"
 
33
#include "s_span.h"
 
34
 
 
35
 
 
36
 
 
37
/* Stencil Logic:
 
38
 
 
39
IF stencil test fails THEN
 
40
   Apply fail-op to stencil value
 
41
   Don't write the pixel (RGBA,Z)
 
42
ELSE
 
43
   IF doing depth test && depth test fails THEN
 
44
      Apply zfail-op to stencil value
 
45
      Write RGBA and Z to appropriate buffers
 
46
   ELSE
 
47
      Apply zpass-op to stencil value
 
48
ENDIF
 
49
 
 
50
*/
 
51
 
 
52
 
 
53
/**
 
54
 * Apply the given stencil operator to the array of stencil values.
 
55
 * Don't touch stencil[i] if mask[i] is zero.
 
56
 * Input:  n - size of stencil array
 
57
 *         oper - the stencil buffer operator
 
58
 *         face - 0 or 1 for front or back face operation
 
59
 *         stencil - array of stencil values
 
60
 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
 
61
 * Output:  stencil - modified values
 
62
 */
 
63
static void
 
64
apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,
 
65
                  GLuint n, GLstencil stencil[], const GLubyte mask[] )
 
66
{
 
67
   const GLstencil ref = ctx->Stencil.Ref[face];
 
68
   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
 
69
   const GLstencil invmask = (GLstencil) (~wrtmask);
 
70
   const GLstencil stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;
 
71
   GLuint i;
 
72
 
 
73
   switch (oper) {
 
74
      case GL_KEEP:
 
75
         /* do nothing */
 
76
         break;
 
77
      case GL_ZERO:
 
78
         if (invmask==0) {
 
79
            for (i=0;i<n;i++) {
 
80
               if (mask[i]) {
 
81
                  stencil[i] = 0;
 
82
               }
 
83
            }
 
84
         }
 
85
         else {
 
86
            for (i=0;i<n;i++) {
 
87
               if (mask[i]) {
 
88
                  stencil[i] = (GLstencil) (stencil[i] & invmask);
 
89
               }
 
90
            }
 
91
         }
 
92
         break;
 
93
      case GL_REPLACE:
 
94
         if (invmask==0) {
 
95
            for (i=0;i<n;i++) {
 
96
               if (mask[i]) {
 
97
                  stencil[i] = ref;
 
98
               }
 
99
            }
 
100
         }
 
101
         else {
 
102
            for (i=0;i<n;i++) {
 
103
               if (mask[i]) {
 
104
                  GLstencil s = stencil[i];
 
105
                  stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
 
106
               }
 
107
            }
 
108
         }
 
109
         break;
 
110
      case GL_INCR:
 
111
         if (invmask==0) {
 
112
            for (i=0;i<n;i++) {
 
113
               if (mask[i]) {
 
114
                  GLstencil s = stencil[i];
 
115
                  if (s < stencilMax) {
 
116
                     stencil[i] = (GLstencil) (s+1);
 
117
                  }
 
118
               }
 
119
            }
 
120
         }
 
121
         else {
 
122
            for (i=0;i<n;i++) {
 
123
               if (mask[i]) {
 
124
                  /* VERIFY logic of adding 1 to a write-masked value */
 
125
                  GLstencil s = stencil[i];
 
126
                  if (s < stencilMax) {
 
127
                     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
 
128
                  }
 
129
               }
 
130
            }
 
131
         }
 
132
         break;
 
133
      case GL_DECR:
 
134
         if (invmask==0) {
 
135
            for (i=0;i<n;i++) {
 
136
               if (mask[i]) {
 
137
                  GLstencil s = stencil[i];
 
138
                  if (s>0) {
 
139
                     stencil[i] = (GLstencil) (s-1);
 
140
                  }
 
141
               }
 
142
            }
 
143
         }
 
144
         else {
 
145
            for (i=0;i<n;i++) {
 
146
               if (mask[i]) {
 
147
                  /* VERIFY logic of subtracting 1 to a write-masked value */
 
148
                  GLstencil s = stencil[i];
 
149
                  if (s>0) {
 
150
                     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
 
151
                  }
 
152
               }
 
153
            }
 
154
         }
 
155
         break;
 
156
      case GL_INCR_WRAP_EXT:
 
157
         if (invmask==0) {
 
158
            for (i=0;i<n;i++) {
 
159
               if (mask[i]) {
 
160
                  stencil[i]++;
 
161
               }
 
162
            }
 
163
         }
 
164
         else {
 
165
            for (i=0;i<n;i++) {
 
166
               if (mask[i]) {
 
167
                  GLstencil s = stencil[i];
 
168
                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
 
169
               }
 
170
            }
 
171
         }
 
172
         break;
 
173
      case GL_DECR_WRAP_EXT:
 
174
         if (invmask==0) {
 
175
            for (i=0;i<n;i++) {
 
176
               if (mask[i]) {
 
177
                  stencil[i]--;
 
178
               }
 
179
            }
 
180
         }
 
181
         else {
 
182
            for (i=0;i<n;i++) {
 
183
               if (mask[i]) {
 
184
                  GLstencil s = stencil[i];
 
185
                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
 
186
               }
 
187
            }
 
188
         }
 
189
         break;
 
190
      case GL_INVERT:
 
191
         if (invmask==0) {
 
192
            for (i=0;i<n;i++) {
 
193
               if (mask[i]) {
 
194
                  GLstencil s = stencil[i];
 
195
                  stencil[i] = (GLstencil) ~s;
 
196
               }
 
197
            }
 
198
         }
 
199
         else {
 
200
            for (i=0;i<n;i++) {
 
201
               if (mask[i]) {
 
202
                  GLstencil s = stencil[i];
 
203
                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
 
204
               }
 
205
            }
 
206
         }
 
207
         break;
 
208
      default:
 
209
         _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
 
210
   }
 
211
}
 
212
 
 
213
 
 
214
 
 
215
 
 
216
/**
 
217
 * Apply stencil test to an array of stencil values (before depth buffering).
 
218
 * Input:  face - 0 or 1 for front or back-face polygons
 
219
 *         n - number of pixels in the array
 
220
 *         stencil - array of [n] stencil values
 
221
 *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
 
222
 * Output:  mask - pixels which fail the stencil test will have their
 
223
 *                 mask flag set to 0.
 
224
 *          stencil - updated stencil values (where the test passed)
 
225
 * Return:  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
 
226
 */
 
227
static GLboolean
 
228
do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],
 
229
                 GLubyte mask[] )
 
230
{
 
231
   GLubyte fail[MAX_WIDTH];
 
232
   GLboolean allfail = GL_FALSE;
 
233
   GLuint i;
 
234
   GLstencil r, s;
 
235
   const GLuint valueMask = ctx->Stencil.ValueMask[face];
 
236
 
 
237
   ASSERT(n <= MAX_WIDTH);
 
238
 
 
239
   /*
 
240
    * Perform stencil test.  The results of this operation are stored
 
241
    * in the fail[] array:
 
242
    *   IF fail[i] is non-zero THEN
 
243
    *       the stencil fail operator is to be applied
 
244
    *   ELSE
 
245
    *       the stencil fail operator is not to be applied
 
246
    *   ENDIF
 
247
    */
 
248
   switch (ctx->Stencil.Function[face]) {
 
249
      case GL_NEVER:
 
250
         /* never pass; always fail */
 
251
         for (i=0;i<n;i++) {
 
252
            if (mask[i]) {
 
253
               mask[i] = 0;
 
254
               fail[i] = 1;
 
255
            }
 
256
            else {
 
257
               fail[i] = 0;
 
258
            }
 
259
         }
 
260
         allfail = GL_TRUE;
 
261
         break;
 
262
      case GL_LESS:
 
263
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
264
         for (i=0;i<n;i++) {
 
265
            if (mask[i]) {
 
266
               s = (GLstencil) (stencil[i] & valueMask);
 
267
               if (r < s) {
 
268
                  /* passed */
 
269
                  fail[i] = 0;
 
270
               }
 
271
               else {
 
272
                  fail[i] = 1;
 
273
                  mask[i] = 0;
 
274
               }
 
275
            }
 
276
            else {
 
277
               fail[i] = 0;
 
278
            }
 
279
         }
 
280
         break;
 
281
      case GL_LEQUAL:
 
282
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
283
         for (i=0;i<n;i++) {
 
284
            if (mask[i]) {
 
285
               s = (GLstencil) (stencil[i] & valueMask);
 
286
               if (r <= s) {
 
287
                  /* pass */
 
288
                  fail[i] = 0;
 
289
               }
 
290
               else {
 
291
                  fail[i] = 1;
 
292
                  mask[i] = 0;
 
293
               }
 
294
            }
 
295
            else {
 
296
               fail[i] = 0;
 
297
            }
 
298
         }
 
299
         break;
 
300
      case GL_GREATER:
 
301
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
302
         for (i=0;i<n;i++) {
 
303
            if (mask[i]) {
 
304
               s = (GLstencil) (stencil[i] & valueMask);
 
305
               if (r > s) {
 
306
                  /* passed */
 
307
                  fail[i] = 0;
 
308
               }
 
309
               else {
 
310
                  fail[i] = 1;
 
311
                  mask[i] = 0;
 
312
               }
 
313
            }
 
314
            else {
 
315
               fail[i] = 0;
 
316
            }
 
317
         }
 
318
         break;
 
319
      case GL_GEQUAL:
 
320
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
321
         for (i=0;i<n;i++) {
 
322
            if (mask[i]) {
 
323
               s = (GLstencil) (stencil[i] & valueMask);
 
324
               if (r >= s) {
 
325
                  /* passed */
 
326
                  fail[i] = 0;
 
327
               }
 
328
               else {
 
329
                  fail[i] = 1;
 
330
                  mask[i] = 0;
 
331
               }
 
332
            }
 
333
            else {
 
334
               fail[i] = 0;
 
335
            }
 
336
         }
 
337
         break;
 
338
      case GL_EQUAL:
 
339
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
340
         for (i=0;i<n;i++) {
 
341
            if (mask[i]) {
 
342
               s = (GLstencil) (stencil[i] & valueMask);
 
343
               if (r == s) {
 
344
                  /* passed */
 
345
                  fail[i] = 0;
 
346
               }
 
347
               else {
 
348
                  fail[i] = 1;
 
349
                  mask[i] = 0;
 
350
               }
 
351
            }
 
352
            else {
 
353
               fail[i] = 0;
 
354
            }
 
355
         }
 
356
         break;
 
357
      case GL_NOTEQUAL:
 
358
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
359
         for (i=0;i<n;i++) {
 
360
            if (mask[i]) {
 
361
               s = (GLstencil) (stencil[i] & valueMask);
 
362
               if (r != s) {
 
363
                  /* passed */
 
364
                  fail[i] = 0;
 
365
               }
 
366
               else {
 
367
                  fail[i] = 1;
 
368
                  mask[i] = 0;
 
369
               }
 
370
            }
 
371
            else {
 
372
               fail[i] = 0;
 
373
            }
 
374
         }
 
375
         break;
 
376
      case GL_ALWAYS:
 
377
         /* always pass */
 
378
         for (i=0;i<n;i++) {
 
379
            fail[i] = 0;
 
380
         }
 
381
         break;
 
382
      default:
 
383
         _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
 
384
         return 0;
 
385
   }
 
386
 
 
387
   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
 
388
      apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
 
389
   }
 
390
 
 
391
   return !allfail;
 
392
}
 
393
 
 
394
 
 
395
 
 
396
/**
 
397
 * Apply stencil and depth testing to the span of pixels.
 
398
 * Both software and hardware stencil buffers are acceptable.
 
399
 * Input:  n - number of pixels in the span
 
400
 *         x, y - location of leftmost pixel in span
 
401
 *         z - array [n] of z values
 
402
 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
 
403
 * Output:  mask - array [n] of flags (1=stencil and depth test passed)
 
404
 * Return: GL_FALSE - all fragments failed the testing
 
405
 *         GL_TRUE - one or more fragments passed the testing
 
406
 *
 
407
 */
 
408
static GLboolean
 
409
stencil_and_ztest_span(GLcontext *ctx, SWspan *span, GLuint face)
 
410
{
 
411
   struct gl_framebuffer *fb = ctx->DrawBuffer;
 
412
   struct gl_renderbuffer *rb = fb->_StencilBuffer;
 
413
   GLstencil stencilRow[MAX_WIDTH];
 
414
   GLstencil *stencil;
 
415
   const GLuint n = span->end;
 
416
   const GLint x = span->x;
 
417
   const GLint y = span->y;
 
418
   GLubyte *mask = span->array->mask;
 
419
 
 
420
   ASSERT((span->arrayMask & SPAN_XY) == 0);
 
421
   ASSERT(ctx->Stencil.Enabled);
 
422
   ASSERT(n <= MAX_WIDTH);
 
423
#ifdef DEBUG
 
424
   if (ctx->Depth.Test) {
 
425
      ASSERT(span->arrayMask & SPAN_Z);
 
426
   }
 
427
#endif
 
428
 
 
429
   stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);
 
430
   if (!stencil) {
 
431
      rb->GetRow(ctx, rb, n, x, y, stencilRow);
 
432
      stencil = stencilRow;
 
433
   }
 
434
 
 
435
   /*
 
436
    * Apply the stencil test to the fragments.
 
437
    * failMask[i] is 1 if the stencil test failed.
 
438
    */
 
439
   if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
 
440
      /* all fragments failed the stencil test, we're done. */
 
441
      span->writeAll = GL_FALSE;
 
442
      if (!rb->GetPointer(ctx, rb, 0, 0)) {
 
443
         /* put updated stencil values into buffer */
 
444
         rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
 
445
      }
 
446
      return GL_FALSE;
 
447
   }
 
448
 
 
449
   /*
 
450
    * Some fragments passed the stencil test, apply depth test to them
 
451
    * and apply Zpass and Zfail stencil ops.
 
452
    */
 
453
   if (ctx->Depth.Test == GL_FALSE) {
 
454
      /*
 
455
       * No depth buffer, just apply zpass stencil function to active pixels.
 
456
       */
 
457
      apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
 
458
   }
 
459
   else {
 
460
      /*
 
461
       * Perform depth buffering, then apply zpass or zfail stencil function.
 
462
       */
 
463
      GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
 
464
      GLuint i;
 
465
 
 
466
      /* save the current mask bits */
 
467
      _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
 
468
 
 
469
      /* apply the depth test */
 
470
      _swrast_depth_test_span(ctx, span);
 
471
 
 
472
      /* Set the stencil pass/fail flags according to result of depth testing.
 
473
       * if oldmask[i] == 0 then
 
474
       *    Don't touch the stencil value
 
475
       * else if oldmask[i] and newmask[i] then
 
476
       *    Depth test passed
 
477
       * else
 
478
       *    assert(oldmask[i] && !newmask[i])
 
479
       *    Depth test failed
 
480
       * endif
 
481
       */
 
482
      for (i=0;i<n;i++) {
 
483
         ASSERT(mask[i] == 0 || mask[i] == 1);
 
484
         passmask[i] = oldmask[i] & mask[i];
 
485
         failmask[i] = oldmask[i] & (mask[i] ^ 1);
 
486
      }
 
487
 
 
488
      /* apply the pass and fail operations */
 
489
      if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
 
490
         apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
 
491
                           n, stencil, failmask );
 
492
      }
 
493
      if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
 
494
         apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
 
495
                           n, stencil, passmask );
 
496
      }
 
497
   }
 
498
 
 
499
   /*
 
500
    * Write updated stencil values back into hardware stencil buffer.
 
501
    */
 
502
   if (!rb->GetPointer(ctx, rb, 0, 0)) {
 
503
      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
 
504
   }
 
505
   
 
506
   span->writeAll = GL_FALSE;
 
507
   
 
508
   return GL_TRUE;  /* one or more fragments passed both tests */
 
509
}
 
510
 
 
511
 
 
512
 
 
513
/*
 
514
 * Return the address of a stencil buffer value given the window coords:
 
515
 */
 
516
#define STENCIL_ADDRESS(X, Y)  (stencilStart + (Y) * stride + (X))
 
517
 
 
518
 
 
519
 
 
520
/**
 
521
 * Apply the given stencil operator for each pixel in the array whose
 
522
 * mask flag is set.
 
523
 * \note  This is for software stencil buffers only.
 
524
 * Input:  n - number of pixels in the span
 
525
 *         x, y - array of [n] pixels
 
526
 *         operator - the stencil buffer operator
 
527
 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
 
528
 */
 
529
static void
 
530
apply_stencil_op_to_pixels( GLcontext *ctx,
 
531
                            GLuint n, const GLint x[], const GLint y[],
 
532
                            GLenum oper, GLuint face, const GLubyte mask[] )
 
533
{
 
534
   struct gl_framebuffer *fb = ctx->DrawBuffer;
 
535
   struct gl_renderbuffer *rb = fb->_StencilBuffer;
 
536
   const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
 
537
   const GLstencil ref = ctx->Stencil.Ref[face];
 
538
   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
 
539
   const GLstencil invmask = (GLstencil) (~wrtmask);
 
540
   GLuint i;
 
541
   GLstencil *stencilStart = (GLubyte *) rb->Data;
 
542
   const GLuint stride = rb->Width;
 
543
 
 
544
   ASSERT(rb->GetPointer(ctx, rb, 0, 0));
 
545
   ASSERT(sizeof(GLstencil) == 1);
 
546
 
 
547
   switch (oper) {
 
548
      case GL_KEEP:
 
549
         /* do nothing */
 
550
         break;
 
551
      case GL_ZERO:
 
552
         if (invmask==0) {
 
553
            for (i=0;i<n;i++) {
 
554
               if (mask[i]) {
 
555
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
556
                  *sptr = 0;
 
557
               }
 
558
            }
 
559
         }
 
560
         else {
 
561
            for (i=0;i<n;i++) {
 
562
               if (mask[i]) {
 
563
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
564
                  *sptr = (GLstencil) (invmask & *sptr);
 
565
               }
 
566
            }
 
567
         }
 
568
         break;
 
569
      case GL_REPLACE:
 
570
         if (invmask==0) {
 
571
            for (i=0;i<n;i++) {
 
572
               if (mask[i]) {
 
573
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
574
                  *sptr = ref;
 
575
               }
 
576
            }
 
577
         }
 
578
         else {
 
579
            for (i=0;i<n;i++) {
 
580
               if (mask[i]) {
 
581
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
582
                  *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
 
583
               }
 
584
            }
 
585
         }
 
586
         break;
 
587
      case GL_INCR:
 
588
         if (invmask==0) {
 
589
            for (i=0;i<n;i++) {
 
590
               if (mask[i]) {
 
591
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
592
                  if (*sptr < stencilMax) {
 
593
                     *sptr = (GLstencil) (*sptr + 1);
 
594
                  }
 
595
               }
 
596
            }
 
597
         }
 
598
         else {
 
599
            for (i=0;i<n;i++) {
 
600
               if (mask[i]) {
 
601
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
602
                  if (*sptr < stencilMax) {
 
603
                     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
 
604
                  }
 
605
               }
 
606
            }
 
607
         }
 
608
         break;
 
609
      case GL_DECR:
 
610
         if (invmask==0) {
 
611
            for (i=0;i<n;i++) {
 
612
               if (mask[i]) {
 
613
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
614
                  if (*sptr>0) {
 
615
                     *sptr = (GLstencil) (*sptr - 1);
 
616
                  }
 
617
               }
 
618
            }
 
619
         }
 
620
         else {
 
621
            for (i=0;i<n;i++) {
 
622
               if (mask[i]) {
 
623
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
624
                  if (*sptr>0) {
 
625
                     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
 
626
                  }
 
627
               }
 
628
            }
 
629
         }
 
630
         break;
 
631
      case GL_INCR_WRAP_EXT:
 
632
         if (invmask==0) {
 
633
            for (i=0;i<n;i++) {
 
634
               if (mask[i]) {
 
635
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
636
                  *sptr = (GLstencil) (*sptr + 1);
 
637
               }
 
638
            }
 
639
         }
 
640
         else {
 
641
            for (i=0;i<n;i++) {
 
642
               if (mask[i]) {
 
643
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
644
                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
 
645
               }
 
646
            }
 
647
         }
 
648
         break;
 
649
      case GL_DECR_WRAP_EXT:
 
650
         if (invmask==0) {
 
651
            for (i=0;i<n;i++) {
 
652
               if (mask[i]) {
 
653
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
654
                  *sptr = (GLstencil) (*sptr - 1);
 
655
               }
 
656
            }
 
657
         }
 
658
         else {
 
659
            for (i=0;i<n;i++) {
 
660
               if (mask[i]) {
 
661
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
662
                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
 
663
               }
 
664
            }
 
665
         }
 
666
         break;
 
667
      case GL_INVERT:
 
668
         if (invmask==0) {
 
669
            for (i=0;i<n;i++) {
 
670
               if (mask[i]) {
 
671
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
672
                  *sptr = (GLstencil) (~*sptr);
 
673
               }
 
674
            }
 
675
         }
 
676
         else {
 
677
            for (i=0;i<n;i++) {
 
678
               if (mask[i]) {
 
679
                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
 
680
                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
 
681
               }
 
682
            }
 
683
         }
 
684
         break;
 
685
      default:
 
686
         _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
 
687
   }
 
688
}
 
689
 
 
690
 
 
691
 
 
692
/**
 
693
 * Apply stencil test to an array of pixels before depth buffering.
 
694
 *
 
695
 * \note Used for software stencil buffer only.
 
696
 * Input:  n - number of pixels in the span
 
697
 *         x, y - array of [n] pixels to stencil
 
698
 *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
 
699
 * Output:  mask - pixels which fail the stencil test will have their
 
700
 *                 mask flag set to 0.
 
701
 * \return  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
 
702
 */
 
703
static GLboolean
 
704
stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
 
705
                     const GLint x[], const GLint y[], GLubyte mask[] )
 
706
{
 
707
   const struct gl_framebuffer *fb = ctx->DrawBuffer;
 
708
   struct gl_renderbuffer *rb = fb->_StencilBuffer;
 
709
   GLubyte fail[MAX_WIDTH];
 
710
   GLstencil r, s;
 
711
   GLuint i;
 
712
   GLboolean allfail = GL_FALSE;
 
713
   const GLuint valueMask = ctx->Stencil.ValueMask[face];
 
714
   const GLstencil *stencilStart = (GLstencil *) rb->Data;
 
715
   const GLuint stride = rb->Width;
 
716
 
 
717
   ASSERT(rb->GetPointer(ctx, rb, 0, 0));
 
718
   ASSERT(sizeof(GLstencil) == 1);
 
719
 
 
720
   /*
 
721
    * Perform stencil test.  The results of this operation are stored
 
722
    * in the fail[] array:
 
723
    *   IF fail[i] is non-zero THEN
 
724
    *       the stencil fail operator is to be applied
 
725
    *   ELSE
 
726
    *       the stencil fail operator is not to be applied
 
727
    *   ENDIF
 
728
    */
 
729
 
 
730
   switch (ctx->Stencil.Function[face]) {
 
731
      case GL_NEVER:
 
732
         /* always fail */
 
733
         for (i=0;i<n;i++) {
 
734
            if (mask[i]) {
 
735
               mask[i] = 0;
 
736
               fail[i] = 1;
 
737
            }
 
738
            else {
 
739
               fail[i] = 0;
 
740
            }
 
741
         }
 
742
         allfail = GL_TRUE;
 
743
         break;
 
744
      case GL_LESS:
 
745
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
746
         for (i=0;i<n;i++) {
 
747
            if (mask[i]) {
 
748
               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
 
749
               s = (GLstencil) (*sptr & valueMask);
 
750
               if (r < s) {
 
751
                  /* passed */
 
752
                  fail[i] = 0;
 
753
               }
 
754
               else {
 
755
                  fail[i] = 1;
 
756
                  mask[i] = 0;
 
757
               }
 
758
            }
 
759
            else {
 
760
               fail[i] = 0;
 
761
            }
 
762
         }
 
763
         break;
 
764
      case GL_LEQUAL:
 
765
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
766
         for (i=0;i<n;i++) {
 
767
            if (mask[i]) {
 
768
               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
 
769
               s = (GLstencil) (*sptr & valueMask);
 
770
               if (r <= s) {
 
771
                  /* pass */
 
772
                  fail[i] = 0;
 
773
               }
 
774
               else {
 
775
                  fail[i] = 1;
 
776
                  mask[i] = 0;
 
777
               }
 
778
            }
 
779
            else {
 
780
               fail[i] = 0;
 
781
            }
 
782
         }
 
783
         break;
 
784
      case GL_GREATER:
 
785
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
786
         for (i=0;i<n;i++) {
 
787
            if (mask[i]) {
 
788
               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
 
789
               s = (GLstencil) (*sptr & valueMask);
 
790
               if (r > s) {
 
791
                  /* passed */
 
792
                  fail[i] = 0;
 
793
               }
 
794
               else {
 
795
                  fail[i] = 1;
 
796
                  mask[i] = 0;
 
797
               }
 
798
            }
 
799
            else {
 
800
               fail[i] = 0;
 
801
            }
 
802
         }
 
803
         break;
 
804
      case GL_GEQUAL:
 
805
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
806
         for (i=0;i<n;i++) {
 
807
            if (mask[i]) {
 
808
               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
 
809
               s = (GLstencil) (*sptr & valueMask);
 
810
               if (r >= s) {
 
811
                  /* passed */
 
812
                  fail[i] = 0;
 
813
               }
 
814
               else {
 
815
                  fail[i] = 1;
 
816
                  mask[i] = 0;
 
817
               }
 
818
            }
 
819
            else {
 
820
               fail[i] = 0;
 
821
            }
 
822
         }
 
823
         break;
 
824
      case GL_EQUAL:
 
825
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
826
         for (i=0;i<n;i++) {
 
827
            if (mask[i]) {
 
828
               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
 
829
               s = (GLstencil) (*sptr & valueMask);
 
830
               if (r == s) {
 
831
                  /* passed */
 
832
                  fail[i] = 0;
 
833
               }
 
834
               else {
 
835
                  fail[i] = 1;
 
836
                  mask[i] = 0;
 
837
               }
 
838
            }
 
839
            else {
 
840
               fail[i] = 0;
 
841
            }
 
842
         }
 
843
         break;
 
844
      case GL_NOTEQUAL:
 
845
         r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
 
846
         for (i=0;i<n;i++) {
 
847
            if (mask[i]) {
 
848
               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
 
849
               s = (GLstencil) (*sptr & valueMask);
 
850
               if (r != s) {
 
851
                  /* passed */
 
852
                  fail[i] = 0;
 
853
               }
 
854
               else {
 
855
                  fail[i] = 1;
 
856
                  mask[i] = 0;
 
857
               }
 
858
            }
 
859
            else {
 
860
               fail[i] = 0;
 
861
            }
 
862
         }
 
863
         break;
 
864
      case GL_ALWAYS:
 
865
         /* always pass */
 
866
         for (i=0;i<n;i++) {
 
867
            fail[i] = 0;
 
868
         }
 
869
         break;
 
870
      default:
 
871
         _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
 
872
         return 0;
 
873
   }
 
874
 
 
875
   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
 
876
      apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
 
877
                                  face, fail );
 
878
   }
 
879
 
 
880
   return !allfail;
 
881
}
 
882
 
 
883
 
 
884
 
 
885
 
 
886
/**
 
887
 * Apply stencil and depth testing to an array of pixels.
 
888
 * This is used both for software and hardware stencil buffers.
 
889
 *
 
890
 * The comments in this function are a bit sparse but the code is
 
891
 * almost identical to stencil_and_ztest_span(), which is well
 
892
 * commented.
 
893
 *
 
894
 * Input:  n - number of pixels in the array
 
895
 *         x, y - array of [n] pixel positions
 
896
 *         z - array [n] of z values
 
897
 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
 
898
 * Output: mask - array [n] of flags (1=stencil and depth test passed)
 
899
 * Return: GL_FALSE - all fragments failed the testing
 
900
 *         GL_TRUE - one or more fragments passed the testing
 
901
 */
 
902
static GLboolean
 
903
stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
 
904
{
 
905
   struct gl_framebuffer *fb = ctx->DrawBuffer;
 
906
   struct gl_renderbuffer *rb = fb->_StencilBuffer;
 
907
   const GLuint n = span->end;
 
908
   const GLint *x = span->array->x;
 
909
   const GLint *y = span->array->y;
 
910
   GLubyte *mask = span->array->mask;
 
911
 
 
912
   ASSERT(span->arrayMask & SPAN_XY);
 
913
   ASSERT(ctx->Stencil.Enabled);
 
914
   ASSERT(n <= MAX_WIDTH);
 
915
 
 
916
   if (!rb->GetPointer(ctx, rb, 0, 0)) {
 
917
      /* No direct access */
 
918
      GLstencil stencil[MAX_WIDTH];
 
919
      GLubyte origMask[MAX_WIDTH];
 
920
 
 
921
      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
 
922
      _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
 
923
 
 
924
      _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
 
925
 
 
926
      (void) do_stencil_test(ctx, face, n, stencil, mask);
 
927
 
 
928
      if (ctx->Depth.Test == GL_FALSE) {
 
929
         apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
 
930
                          n, stencil, mask);
 
931
      }
 
932
      else {
 
933
         _swrast_depth_test_span(ctx, span);
 
934
 
 
935
         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
 
936
            GLubyte failmask[MAX_WIDTH];
 
937
            GLuint i;
 
938
            for (i = 0; i < n; i++) {
 
939
               ASSERT(mask[i] == 0 || mask[i] == 1);
 
940
               failmask[i] = origMask[i] & (mask[i] ^ 1);
 
941
            }
 
942
            apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
 
943
                             n, stencil, failmask);
 
944
         }
 
945
         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
 
946
            GLubyte passmask[MAX_WIDTH];
 
947
            GLuint i;
 
948
            for (i = 0; i < n; i++) {
 
949
               ASSERT(mask[i] == 0 || mask[i] == 1);
 
950
               passmask[i] = origMask[i] & mask[i];
 
951
            }
 
952
            apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
 
953
                             n, stencil, passmask);
 
954
         }
 
955
      }
 
956
 
 
957
      /* Write updated stencil values into hardware stencil buffer */
 
958
      rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
 
959
 
 
960
      return GL_TRUE;
 
961
   }
 
962
   else {
 
963
      /* Direct access to stencil buffer */
 
964
 
 
965
      if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
 
966
         /* all fragments failed the stencil test, we're done. */
 
967
         return GL_FALSE;
 
968
      }
 
969
 
 
970
      if (ctx->Depth.Test==GL_FALSE) {
 
971
         apply_stencil_op_to_pixels(ctx, n, x, y,
 
972
                                    ctx->Stencil.ZPassFunc[face], face, mask);
 
973
      }
 
974
      else {
 
975
         GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
 
976
         GLuint i;
 
977
 
 
978
         _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
 
979
 
 
980
         _swrast_depth_test_span(ctx, span);
 
981
 
 
982
         for (i=0;i<n;i++) {
 
983
            ASSERT(mask[i] == 0 || mask[i] == 1);
 
984
            passmask[i] = oldmask[i] & mask[i];
 
985
            failmask[i] = oldmask[i] & (mask[i] ^ 1);
 
986
         }
 
987
 
 
988
         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
 
989
            apply_stencil_op_to_pixels(ctx, n, x, y,
 
990
                                       ctx->Stencil.ZFailFunc[face],
 
991
                                       face, failmask);
 
992
         }
 
993
         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
 
994
            apply_stencil_op_to_pixels(ctx, n, x, y,
 
995
                                       ctx->Stencil.ZPassFunc[face],
 
996
                                       face, passmask);
 
997
         }
 
998
      }
 
999
 
 
1000
      return GL_TRUE;  /* one or more fragments passed both tests */
 
1001
   }
 
1002
}
 
1003
 
 
1004
 
 
1005
/**
 
1006
 * /return GL_TRUE = one or more fragments passed,
 
1007
 * GL_FALSE = all fragments failed.
 
1008
 */
 
1009
GLboolean
 
1010
_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
 
1011
{
 
1012
   if (span->arrayMask & SPAN_XY)
 
1013
      return stencil_and_ztest_pixels(ctx, span, span->facing);
 
1014
   else
 
1015
      return stencil_and_ztest_span(ctx, span, span->facing);
 
1016
}
 
1017
 
 
1018
 
 
1019
#if 0
 
1020
GLuint
 
1021
clip_span(GLuint bufferWidth, GLuint bufferHeight,
 
1022
          GLint x, GLint y, GLuint *count)
 
1023
{
 
1024
   GLuint n = *count;
 
1025
   GLuint skipPixels = 0;
 
1026
 
 
1027
   if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
 
1028
      /* totally out of bounds */
 
1029
      n = 0;
 
1030
   }
 
1031
   else {
 
1032
      /* left clip */
 
1033
      if (x < 0) {
 
1034
         skipPixels = -x;
 
1035
         x = 0;
 
1036
         n -= skipPixels;
 
1037
      }
 
1038
      /* right clip */
 
1039
      if (x + n > bufferWidth) {
 
1040
         GLint dx = x + n - bufferWidth;
 
1041
         n -= dx;
 
1042
      }
 
1043
   }
 
1044
 
 
1045
   *count = n;
 
1046
 
 
1047
   return skipPixels;
 
1048
}
 
1049
#endif
 
1050
 
 
1051
 
 
1052
/**
 
1053
 * Return a span of stencil values from the stencil buffer.
 
1054
 * Used for glRead/CopyPixels
 
1055
 * Input:  n - how many pixels
 
1056
 *         x,y - location of first pixel
 
1057
 * Output:  stencil - the array of stencil values
 
1058
 */
 
1059
void
 
1060
_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,
 
1061
                          GLint n, GLint x, GLint y, GLstencil stencil[])
 
1062
{
 
1063
   if (y < 0 || y >= (GLint) rb->Height ||
 
1064
       x + n <= 0 || x >= (GLint) rb->Width) {
 
1065
      /* span is completely outside framebuffer */
 
1066
      return; /* undefined values OK */
 
1067
   }
 
1068
 
 
1069
   if (x < 0) {
 
1070
      GLint dx = -x;
 
1071
      x = 0;
 
1072
      n -= dx;
 
1073
      stencil += dx;
 
1074
   }
 
1075
   if (x + n > (GLint) rb->Width) {
 
1076
      GLint dx = x + n - rb->Width;
 
1077
      n -= dx;
 
1078
   }
 
1079
   if (n <= 0) {
 
1080
      return;
 
1081
   }
 
1082
 
 
1083
   rb->GetRow(ctx, rb, n, x, y, stencil);
 
1084
}
 
1085
 
 
1086
 
 
1087
 
 
1088
/**
 
1089
 * Write a span of stencil values to the stencil buffer.  This function
 
1090
 * applies the stencil write mask when needed.
 
1091
 * Used for glDraw/CopyPixels
 
1092
 * Input:  n - how many pixels
 
1093
 *         x, y - location of first pixel
 
1094
 *         stencil - the array of stencil values
 
1095
 */
 
1096
void
 
1097
_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,
 
1098
                           const GLstencil stencil[] )
 
1099
{
 
1100
   struct gl_framebuffer *fb = ctx->DrawBuffer;
 
1101
   struct gl_renderbuffer *rb = fb->_StencilBuffer;
 
1102
   const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
 
1103
   const GLuint stencilMask = ctx->Stencil.WriteMask[0];
 
1104
 
 
1105
   if (y < 0 || y >= (GLint) rb->Height ||
 
1106
       x + n <= 0 || x >= (GLint) rb->Width) {
 
1107
      /* span is completely outside framebuffer */
 
1108
      return; /* undefined values OK */
 
1109
   }
 
1110
   if (x < 0) {
 
1111
      GLint dx = -x;
 
1112
      x = 0;
 
1113
      n -= dx;
 
1114
      stencil += dx;
 
1115
   }
 
1116
   if (x + n > (GLint) rb->Width) {
 
1117
      GLint dx = x + n - rb->Width;
 
1118
      n -= dx;
 
1119
   }
 
1120
   if (n <= 0) {
 
1121
      return;
 
1122
   }
 
1123
 
 
1124
   if ((stencilMask & stencilMax) != stencilMax) {
 
1125
      /* need to apply writemask */
 
1126
      GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
 
1127
      GLint i;
 
1128
      rb->GetRow(ctx, rb, n, x, y, destVals);
 
1129
      for (i = 0; i < n; i++) {
 
1130
         newVals[i]
 
1131
            = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
 
1132
      }
 
1133
      rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
 
1134
   }
 
1135
   else {
 
1136
      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
 
1137
   }
 
1138
}
 
1139
 
 
1140
 
 
1141
 
 
1142
/**
 
1143
 * Clear the stencil buffer.
 
1144
 */
 
1145
void
 
1146
_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
 
1147
{
 
1148
   const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
 
1149
   const GLuint mask = ctx->Stencil.WriteMask[0];
 
1150
   const GLuint invMask = ~mask;
 
1151
   const GLuint clearVal = (ctx->Stencil.Clear & mask);
 
1152
   const GLuint stencilMax = (1 << stencilBits) - 1;
 
1153
   GLint x, y, width, height;
 
1154
 
 
1155
   if (!rb || mask == 0)
 
1156
      return;
 
1157
 
 
1158
   ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
 
1159
          rb->DataType == GL_UNSIGNED_SHORT);
 
1160
 
 
1161
   ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
 
1162
 
 
1163
   /* compute region to clear */
 
1164
   x = ctx->DrawBuffer->_Xmin;
 
1165
   y = ctx->DrawBuffer->_Ymin;
 
1166
   width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
 
1167
   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
 
1168
 
 
1169
   if (rb->GetPointer(ctx, rb, 0, 0)) {
 
1170
      /* Direct buffer access */
 
1171
      if ((mask & stencilMax) != stencilMax) {
 
1172
         /* need to mask the clear */
 
1173
         if (rb->DataType == GL_UNSIGNED_BYTE) {
 
1174
            GLint i, j;
 
1175
            for (i = 0; i < height; i++) {
 
1176
               GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
 
1177
               for (j = 0; j < width; j++) {
 
1178
                  stencil[j] = (stencil[j] & invMask) | clearVal;
 
1179
               }
 
1180
            }
 
1181
         }
 
1182
         else {
 
1183
            GLint i, j;
 
1184
            for (i = 0; i < height; i++) {
 
1185
               GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
 
1186
               for (j = 0; j < width; j++) {
 
1187
                  stencil[j] = (stencil[j] & invMask) | clearVal;
 
1188
               }
 
1189
            }
 
1190
         }
 
1191
      }
 
1192
      else {
 
1193
         /* no bit masking */
 
1194
         if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
 
1195
            /* optimized case */
 
1196
            /* Note: bottom-to-top raster assumed! */
 
1197
            GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
 
1198
            GLuint len = width * height * sizeof(GLubyte);
 
1199
            _mesa_memset(stencil, clearVal, len);
 
1200
         }
 
1201
         else {
 
1202
            /* general case */
 
1203
            GLint i;
 
1204
            for (i = 0; i < height; i++) {
 
1205
               GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
 
1206
               if (rb->DataType == GL_UNSIGNED_BYTE) {
 
1207
                  _mesa_memset(stencil, clearVal, width);
 
1208
               }
 
1209
               else {
 
1210
                  _mesa_memset16((short unsigned int*) stencil, clearVal, width);
 
1211
               }
 
1212
            }
 
1213
         }
 
1214
      }
 
1215
   }
 
1216
   else {
 
1217
      /* no direct access */
 
1218
      if ((mask & stencilMax) != stencilMax) {
 
1219
         /* need to mask the clear */
 
1220
         if (rb->DataType == GL_UNSIGNED_BYTE) {
 
1221
            GLint i, j;
 
1222
            for (i = 0; i < height; i++) {
 
1223
               GLubyte stencil[MAX_WIDTH];
 
1224
               rb->GetRow(ctx, rb, width, x, y + i, stencil);
 
1225
               for (j = 0; j < width; j++) {
 
1226
                  stencil[j] = (stencil[j] & invMask) | clearVal;
 
1227
               }
 
1228
               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
 
1229
            }
 
1230
         }
 
1231
         else {
 
1232
            GLint i, j;
 
1233
            for (i = 0; i < height; i++) {
 
1234
               GLushort stencil[MAX_WIDTH];
 
1235
               rb->GetRow(ctx, rb, width, x, y + i, stencil);
 
1236
               for (j = 0; j < width; j++) {
 
1237
                  stencil[j] = (stencil[j] & invMask) | clearVal;
 
1238
               }
 
1239
               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
 
1240
            }
 
1241
         }
 
1242
      }
 
1243
      else {
 
1244
         /* no bit masking */
 
1245
         const GLubyte clear8 = (GLubyte) clearVal;
 
1246
         const GLushort clear16 = (GLushort) clearVal;
 
1247
         const void *clear;
 
1248
         GLint i;
 
1249
         if (rb->DataType == GL_UNSIGNED_BYTE) {
 
1250
            clear = &clear8;
 
1251
         }
 
1252
         else {
 
1253
            clear = &clear16;
 
1254
         }
 
1255
         for (i = 0; i < height; i++) {
 
1256
            rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);
 
1257
         }
 
1258
      }
 
1259
   }
 
1260
}