Subversion Repositories shark

Rev

Details | Last modification | View Log | RSS feed

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