ReactOS  0.4.13-dev-257-gfabbd7c
stencil.c
Go to the documentation of this file.
1 /* $Id: stencil.c,v 1.8 1998/01/01 00:52:11 brianp Exp $ */
2 
3 /*
4  * Mesa 3-D graphics library
5  * Version: 2.6
6  * Copyright (C) 1995-1997 Brian Paul
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the Free
20  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21  */
22 
23 
24 /*
25  * $Log: stencil.c,v $
26  * Revision 1.8 1998/01/01 00:52:11 brianp
27  * added some tests to prevent crashing if Driver.DepthTestPixels not defined
28  *
29  * Revision 1.7 1997/07/24 01:21:56 brianp
30  * changed precompiled header symbol from PCH to PC_HEADER
31  *
32  * Revision 1.6 1997/05/28 03:26:29 brianp
33  * added precompiled header (PCH) support
34  *
35  * Revision 1.5 1997/04/29 01:26:37 brianp
36  * fixed a few return statements which were missing values
37  *
38  * Revision 1.4 1997/04/20 20:29:11 brianp
39  * replaced abort() with gl_problem()
40  *
41  * Revision 1.3 1997/02/27 19:58:35 brianp
42  * don't try to clear stencil buffer if there isn't one
43  *
44  * Revision 1.2 1996/09/15 14:18:55 brianp
45  * now use GLframebuffer and GLvisual
46  *
47  * Revision 1.1 1996/09/13 01:38:16 brianp
48  * Initial revision
49  *
50  */
51 
52 
53 #ifdef PC_HEADER
54 #include "all.h"
55 #else
56 #include <stdlib.h>
57 #include <string.h>
58 #include "context.h"
59 #include "dlist.h"
60 #include "macros.h"
61 #include "pb.h"
62 #include "stencil.h"
63 #include "types.h"
64 #endif
65 
66 
67 /*
68  * Return the address of a stencil buffer value given the window coords:
69  */
70 #define STENCIL_ADDRESS(X,Y) (ctx->Buffer->Stencil + ctx->Buffer->Width * (Y) + (X))
71 
72 
74 {
75  if (INSIDE_BEGIN_END(ctx)) {
76  gl_error( ctx, GL_INVALID_OPERATION, "glClearStencil" );
77  return;
78  }
79  ctx->Stencil.Clear = (GLstencil) s;
80 }
81 
82 
83 
85 {
86  GLint maxref;
87 
88  if (INSIDE_BEGIN_END(ctx)) {
89  gl_error( ctx, GL_INVALID_OPERATION, "glStencilFunc" );
90  return;
91  }
92 
93  switch (func) {
94  case GL_NEVER:
95  case GL_LESS:
96  case GL_LEQUAL:
97  case GL_GREATER:
98  case GL_GEQUAL:
99  case GL_EQUAL:
100  case GL_NOTEQUAL:
101  case GL_ALWAYS:
102  ctx->Stencil.Function = func;
103  break;
104  default:
105  gl_error( ctx, GL_INVALID_ENUM, "glStencilFunc" );
106  return;
107  }
108 
109  maxref = (1 << STENCIL_BITS) - 1;
110  ctx->Stencil.Ref = CLAMP( ref, 0, maxref );
111  ctx->Stencil.ValueMask = mask;
112 }
113 
114 
115 
117 {
118  if (INSIDE_BEGIN_END(ctx)) {
119  gl_error( ctx, GL_INVALID_OPERATION, "glStencilMask" );
120  return;
121  }
122  ctx->Stencil.WriteMask = (GLstencil) mask;
123 }
124 
125 
126 
127 void gl_StencilOp( GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass )
128 {
129  if (INSIDE_BEGIN_END(ctx)) {
130  gl_error( ctx, GL_INVALID_OPERATION, "glStencilOp" );
131  return;
132  }
133  switch (fail) {
134  case GL_KEEP:
135  case GL_ZERO:
136  case GL_REPLACE:
137  case GL_INCR:
138  case GL_DECR:
139  case GL_INVERT:
140  ctx->Stencil.FailFunc = fail;
141  break;
142  default:
143  gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
144  return;
145  }
146  switch (zfail) {
147  case GL_KEEP:
148  case GL_ZERO:
149  case GL_REPLACE:
150  case GL_INCR:
151  case GL_DECR:
152  case GL_INVERT:
153  ctx->Stencil.ZFailFunc = zfail;
154  break;
155  default:
156  gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
157  return;
158  }
159  switch (zpass) {
160  case GL_KEEP:
161  case GL_ZERO:
162  case GL_REPLACE:
163  case GL_INCR:
164  case GL_DECR:
165  case GL_INVERT:
166  ctx->Stencil.ZPassFunc = zpass;
167  break;
168  default:
169  gl_error( ctx, GL_INVALID_ENUM, "glStencilOp" );
170  return;
171  }
172 }
173 
174 
175 
176 /* Stencil Logic:
177 
178 IF stencil test fails THEN
179  Don't write the pixel (RGBA,Z)
180  Execute FailOp
181 ELSE
182  Write the pixel
183 ENDIF
184 
185 Perform Depth Test
186 
187 IF depth test passes OR no depth buffer THEN
188  Execute ZPass
189  Write the pixel
190 ELSE
191  Execute ZFail
192 ENDIF
193 
194 */
195 
196 
197 
198 
199 /*
200  * Apply the given stencil operator for each pixel in the span whose
201  * mask flag is set.
202  * Input: n - number of pixels in the span
203  * x, y - location of leftmost pixel in the span
204  * oper - the stencil buffer operator
205  * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
206  */
208  GLuint n, GLint x, GLint y,
209  GLenum oper, GLubyte mask[] )
210 {
211  GLint i;
212  GLstencil s, ref;
213  GLstencil wrtmask, invmask;
215 
216  wrtmask = ctx->Stencil.WriteMask;
217  invmask = ~ctx->Stencil.WriteMask;
218  ref = ctx->Stencil.Ref;
219  stencil = STENCIL_ADDRESS( x, y );
220 
221  switch (oper) {
222  case GL_KEEP:
223  /* do nothing */
224  break;
225  case GL_ZERO:
226  if (invmask==0) {
227  for (i=0;i<n;i++) {
228  if (mask[i]) {
229  stencil[i] = 0;
230  }
231  }
232  }
233  else {
234  for (i=0;i<n;i++) {
235  if (mask[i]) {
236  stencil[i] = stencil[i] & invmask;
237  }
238  }
239  }
240  break;
241  case GL_REPLACE:
242  if (invmask==0) {
243  for (i=0;i<n;i++) {
244  if (mask[i]) {
245  stencil[i] = ref;
246  }
247  }
248  }
249  else {
250  for (i=0;i<n;i++) {
251  if (mask[i]) {
252  s = stencil[i];
253  stencil[i] = (invmask & s ) | (wrtmask & ref);
254  }
255  }
256  }
257  break;
258  case GL_INCR:
259  if (invmask==0) {
260  for (i=0;i<n;i++) {
261  if (mask[i]) {
262  s = stencil[i];
263  if (s<0xff) {
264  stencil[i] = s+1;
265  }
266  }
267  }
268  }
269  else {
270  for (i=0;i<n;i++) {
271  if (mask[i]) {
272  /* VERIFY logic of adding 1 to a write-masked value */
273  s = stencil[i];
274  if (s<0xff) {
275  stencil[i] = (invmask & s) | (wrtmask & (s+1));
276  }
277  }
278  }
279  }
280  break;
281  case GL_DECR:
282  if (invmask==0) {
283  for (i=0;i<n;i++) {
284  if (mask[i]) {
285  s = stencil[i];
286  if (s>0) {
287  stencil[i] = s-1;
288  }
289  }
290  }
291  }
292  else {
293  for (i=0;i<n;i++) {
294  if (mask[i]) {
295  /* VERIFY logic of subtracting 1 to a write-masked value */
296  s = stencil[i];
297  if (s>0) {
298  stencil[i] = (invmask & s) | (wrtmask & (s-1));
299  }
300  }
301  }
302  }
303  break;
304  case GL_INVERT:
305  if (invmask==0) {
306  for (i=0;i<n;i++) {
307  if (mask[i]) {
308  s = stencil[i];
309  stencil[i] = ~s;
310  }
311  }
312  }
313  else {
314  for (i=0;i<n;i++) {
315  if (mask[i]) {
316  s = stencil[i];
317  stencil[i] = (invmask & s) | (wrtmask & ~s);
318  }
319  }
320  }
321  break;
322  default:
323  gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_span");
324  }
325 }
326 
327 
328 
329 
330 /*
331  * Apply stencil test to a span of pixels before depth buffering.
332  * Input: n - number of pixels in the span
333  * x, y - coordinate of left-most pixel in the span
334  * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
335  * Output: mask - pixels which fail the stencil test will have their
336  * mask flag set to 0.
337  * Return: 0 = all pixels failed, 1 = zero or more pixels passed.
338  */
340  GLuint n, GLint x, GLint y, GLubyte mask[] )
341 {
342  GLubyte fail[MAX_WIDTH];
343  GLint allfail = 0;
344  GLuint i;
345  GLstencil r, s;
347 
348  stencil = STENCIL_ADDRESS( x, y );
349 
350  /*
351  * Perform stencil test. The results of this operation are stored
352  * in the fail[] array:
353  * IF fail[i] is non-zero THEN
354  * the stencil fail operator is to be applied
355  * ELSE
356  * the stencil fail operator is not to be applied
357  * ENDIF
358  */
359  switch (ctx->Stencil.Function) {
360  case GL_NEVER:
361  /* always fail */
362  for (i=0;i<n;i++) {
363  if (mask[i]) {
364  mask[i] = 0;
365  fail[i] = 1;
366  }
367  else {
368  fail[i] = 0;
369  }
370  }
371  allfail = 1;
372  break;
373  case GL_LESS:
374  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
375  for (i=0;i<n;i++) {
376  if (mask[i]) {
377  s = stencil[i] & ctx->Stencil.ValueMask;
378  if (r < s) {
379  /* passed */
380  fail[i] = 0;
381  }
382  else {
383  fail[i] = 1;
384  mask[i] = 0;
385  }
386  }
387  else {
388  fail[i] = 0;
389  }
390  }
391  break;
392  case GL_LEQUAL:
393  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
394  for (i=0;i<n;i++) {
395  if (mask[i]) {
396  s = stencil[i] & ctx->Stencil.ValueMask;
397  if (r <= s) {
398  /* pass */
399  fail[i] = 0;
400  }
401  else {
402  fail[i] = 1;
403  mask[i] = 0;
404  }
405  }
406  else {
407  fail[i] = 0;
408  }
409  }
410  break;
411  case GL_GREATER:
412  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
413  for (i=0;i<n;i++) {
414  if (mask[i]) {
415  s = stencil[i] & ctx->Stencil.ValueMask;
416  if (r > s) {
417  /* passed */
418  fail[i] = 0;
419  }
420  else {
421  fail[i] = 1;
422  mask[i] = 0;
423  }
424  }
425  else {
426  fail[i] = 0;
427  }
428  }
429  break;
430  case GL_GEQUAL:
431  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
432  for (i=0;i<n;i++) {
433  if (mask[i]) {
434  s = stencil[i] & ctx->Stencil.ValueMask;
435  if (r >= s) {
436  /* passed */
437  fail[i] = 0;
438  }
439  else {
440  fail[i] = 1;
441  mask[i] = 0;
442  }
443  }
444  else {
445  fail[i] = 0;
446  }
447  }
448  break;
449  case GL_EQUAL:
450  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
451  for (i=0;i<n;i++) {
452  if (mask[i]) {
453  s = stencil[i] & ctx->Stencil.ValueMask;
454  if (r == s) {
455  /* passed */
456  fail[i] = 0;
457  }
458  else {
459  fail[i] = 1;
460  mask[i] = 0;
461  }
462  }
463  else {
464  fail[i] = 0;
465  }
466  }
467  break;
468  case GL_NOTEQUAL:
469  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
470  for (i=0;i<n;i++) {
471  if (mask[i]) {
472  s = stencil[i] & ctx->Stencil.ValueMask;
473  if (r != s) {
474  /* passed */
475  fail[i] = 0;
476  }
477  else {
478  fail[i] = 1;
479  mask[i] = 0;
480  }
481  }
482  else {
483  fail[i] = 0;
484  }
485  }
486  break;
487  case GL_ALWAYS:
488  /* always pass */
489  for (i=0;i<n;i++) {
490  fail[i] = 0;
491  }
492  break;
493  default:
494  gl_problem(ctx, "Bad stencil func in gl_stencil_span");
495  return 0;
496  }
497 
498  apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
499 
500  return (allfail) ? 0 : 1;
501 }
502 
503 
504 
505 
506 /*
507  * Apply the combination depth-buffer/stencil operator to a span of pixels.
508  * Input: n - number of pixels in the span
509  * x, y - location of leftmost pixel in span
510  * z - array [n] of z values
511  * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
512  * Output: mask - array [n] of flags (1=depth test passed, 0=failed)
513  */
515  GLuint n, GLint x, GLint y, const GLdepth z[],
516  GLubyte mask[] )
517 {
518  if (ctx->Depth.Test==GL_FALSE) {
519  /*
520  * No depth buffer, just apply zpass stencil function to active pixels.
521  */
522  apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
523  }
524  else {
525  /*
526  * Perform depth buffering, then apply zpass or zfail stencil function.
527  */
528  GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
529  GLuint i;
530 
531  /* init pass and fail masks to zero, copy mask[] to oldmask[] */
532  for (i=0;i<n;i++) {
533  passmask[i] = failmask[i] = 0;
534  oldmask[i] = mask[i];
535  }
536 
537  /* apply the depth test */
538  if (ctx->Driver.DepthTestSpan)
539  (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
540 
541  /* set the stencil pass/fail flags according to result of depth test */
542  for (i=0;i<n;i++) {
543  if (oldmask[i]) {
544  if (mask[i]) {
545  passmask[i] = 1;
546  }
547  else {
548  failmask[i] = 1;
549  }
550  }
551  }
552 
553  /* apply the pass and fail operations */
554  apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZFailFunc, failmask );
555  apply_stencil_op_to_span( ctx, n, x, y, ctx->Stencil.ZPassFunc, passmask );
556  }
557 }
558 
559 
560 
561 
562 /*
563  * Apply the given stencil operator for each pixel in the array whose
564  * mask flag is set.
565  * Input: n - number of pixels in the span
566  * x, y - array of [n] pixels
567  * operator - the stencil buffer operator
568  * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
569  */
571  GLuint n, const GLint x[],
572  const GLint y[],
573  GLenum oper, GLubyte mask[] )
574 {
575  GLint i;
576  GLstencil ref;
577  GLstencil wrtmask, invmask;
578 
579  wrtmask = ctx->Stencil.WriteMask;
580  invmask = ~ctx->Stencil.WriteMask;
581 
582  ref = ctx->Stencil.Ref;
583 
584  switch (oper) {
585  case GL_KEEP:
586  /* do nothing */
587  break;
588  case GL_ZERO:
589  if (invmask==0) {
590  for (i=0;i<n;i++) {
591  if (mask[i]) {
592  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
593  *sptr = 0;
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  *sptr = invmask & *sptr;
602  }
603  }
604  }
605  break;
606  case GL_REPLACE:
607  if (invmask==0) {
608  for (i=0;i<n;i++) {
609  if (mask[i]) {
610  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
611  *sptr = ref;
612  }
613  }
614  }
615  else {
616  for (i=0;i<n;i++) {
617  if (mask[i]) {
618  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
619  *sptr = (invmask & *sptr ) | (wrtmask & ref);
620  }
621  }
622  }
623  break;
624  case GL_INCR:
625  if (invmask==0) {
626  for (i=0;i<n;i++) {
627  if (mask[i]) {
628  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
629  if (*sptr < 0xff) {
630  *sptr = *sptr + 1;
631  }
632  }
633  }
634  }
635  else {
636  for (i=0;i<n;i++) {
637  if (mask[i]) {
638  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
639  if (*sptr<0xff) {
640  *sptr = (invmask & *sptr) | (wrtmask & (*sptr+1));
641  }
642  }
643  }
644  }
645  break;
646  case GL_DECR:
647  if (invmask==0) {
648  for (i=0;i<n;i++) {
649  if (mask[i]) {
650  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
651  if (*sptr>0) {
652  *sptr = *sptr - 1;
653  }
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  if (*sptr>0) {
662  *sptr = (invmask & *sptr) | (wrtmask & (*sptr-1));
663  }
664  }
665  }
666  }
667  break;
668  case GL_INVERT:
669  if (invmask==0) {
670  for (i=0;i<n;i++) {
671  if (mask[i]) {
672  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
673  *sptr = ~*sptr;
674  }
675  }
676  }
677  else {
678  for (i=0;i<n;i++) {
679  if (mask[i]) {
680  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
681  *sptr = (invmask & *sptr) | (wrtmask & ~*sptr);
682  }
683  }
684  }
685  break;
686  default:
687  gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
688  }
689 }
690 
691 
692 
693 /*
694  * Apply stencil test to an array of pixels before depth buffering.
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: 0 = all pixels failed, 1 = zero or more pixels passed.
701  */
703  GLuint n, const GLint x[], const GLint y[],
704  GLubyte mask[] )
705 {
706  GLubyte fail[PB_SIZE];
707  GLstencil r, s;
708  GLuint i;
709  GLint allfail = 0;
710 
711  /*
712  * Perform stencil test. The results of this operation are stored
713  * in the fail[] array:
714  * IF fail[i] is non-zero THEN
715  * the stencil fail operator is to be applied
716  * ELSE
717  * the stencil fail operator is not to be applied
718  * ENDIF
719  */
720 
721  switch (ctx->Stencil.Function) {
722  case GL_NEVER:
723  /* always fail */
724  for (i=0;i<n;i++) {
725  if (mask[i]) {
726  mask[i] = 0;
727  fail[i] = 1;
728  }
729  else {
730  fail[i] = 0;
731  }
732  }
733  allfail = 1;
734  break;
735  case GL_LESS:
736  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
737  for (i=0;i<n;i++) {
738  if (mask[i]) {
739  GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
740  s = *sptr & ctx->Stencil.ValueMask;
741  if (r < s) {
742  /* passed */
743  fail[i] = 0;
744  }
745  else {
746  fail[i] = 1;
747  mask[i] = 0;
748  }
749  }
750  else {
751  fail[i] = 0;
752  }
753  }
754  break;
755  case GL_LEQUAL:
756  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
757  for (i=0;i<n;i++) {
758  if (mask[i]) {
759  GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
760  s = *sptr & ctx->Stencil.ValueMask;
761  if (r <= s) {
762  /* pass */
763  fail[i] = 0;
764  }
765  else {
766  fail[i] = 1;
767  mask[i] = 0;
768  }
769  }
770  else {
771  fail[i] = 0;
772  }
773  }
774  break;
775  case GL_GREATER:
776  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
777  for (i=0;i<n;i++) {
778  if (mask[i]) {
779  GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
780  s = *sptr & ctx->Stencil.ValueMask;
781  if (r > s) {
782  /* passed */
783  fail[i] = 0;
784  }
785  else {
786  fail[i] = 1;
787  mask[i] = 0;
788  }
789  }
790  else {
791  fail[i] = 0;
792  }
793  }
794  break;
795  case GL_GEQUAL:
796  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
797  for (i=0;i<n;i++) {
798  if (mask[i]) {
799  GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
800  s = *sptr & ctx->Stencil.ValueMask;
801  if (r >= s) {
802  /* passed */
803  fail[i] = 0;
804  }
805  else {
806  fail[i] = 1;
807  mask[i] = 0;
808  }
809  }
810  else {
811  fail[i] = 0;
812  }
813  }
814  break;
815  case GL_EQUAL:
816  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
817  for (i=0;i<n;i++) {
818  if (mask[i]) {
819  GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
820  s = *sptr & ctx->Stencil.ValueMask;
821  if (r == s) {
822  /* passed */
823  fail[i] = 0;
824  }
825  else {
826  fail[i] = 1;
827  mask[i] = 0;
828  }
829  }
830  else {
831  fail[i] = 0;
832  }
833  }
834  break;
835  case GL_NOTEQUAL:
836  r = ctx->Stencil.Ref & ctx->Stencil.ValueMask;
837  for (i=0;i<n;i++) {
838  if (mask[i]) {
839  GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
840  s = *sptr & ctx->Stencil.ValueMask;
841  if (r != s) {
842  /* passed */
843  fail[i] = 0;
844  }
845  else {
846  fail[i] = 1;
847  mask[i] = 0;
848  }
849  }
850  else {
851  fail[i] = 0;
852  }
853  }
854  break;
855  case GL_ALWAYS:
856  /* always pass */
857  for (i=0;i<n;i++) {
858  fail[i] = 0;
859  }
860  break;
861  default:
862  gl_problem(ctx, "Bad stencil func in gl_stencil_pixels");
863  return 0;
864  }
865 
866  apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
867 
868  return (allfail) ? 0 : 1;
869 }
870 
871 
872 
873 
874 /*
875  * Apply the combination depth-buffer/stencil operator to a span of pixels.
876  * Input: n - number of pixels in the span
877  * x, y - array of [n] pixels to stencil
878  * z - array [n] of z values
879  * Input: mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
880  * Output: mask - array [n] of flags (1=depth test passed, 0=failed)
881  */
883  GLuint n, const GLint x[], const GLint y[],
884  const GLdepth z[], GLubyte mask[] )
885 {
886  if (ctx->Depth.Test==GL_FALSE) {
887  /*
888  * No depth buffer, just apply zpass stencil function to active pixels.
889  */
890  apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
891  }
892  else {
893  /*
894  * Perform depth buffering, then apply zpass or zfail stencil function.
895  */
896  GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
897  GLuint i;
898 
899  /* init pass and fail masks to zero */
900  for (i=0;i<n;i++) {
901  passmask[i] = failmask[i] = 0;
902  oldmask[i] = mask[i];
903  }
904 
905  /* apply the depth test */
906  if (ctx->Driver.DepthTestPixels)
907  (*ctx->Driver.DepthTestPixels)( ctx, n, x, y, z, mask );
908 
909  /* set the stencil pass/fail flags according to result of depth test */
910  for (i=0;i<n;i++) {
911  if (oldmask[i]) {
912  if (mask[i]) {
913  passmask[i] = 1;
914  }
915  else {
916  failmask[i] = 1;
917  }
918  }
919  }
920 
921  /* apply the pass and fail operations */
923  ctx->Stencil.ZFailFunc, failmask );
925  ctx->Stencil.ZPassFunc, passmask );
926  }
927 
928 }
929 
930 
931 
932 /*
933  * Return a span of stencil values from the stencil buffer.
934  * Input: n - how many pixels
935  * x,y - location of first pixel
936  * Output: stencil - the array of stencil values
937  */
940 {
941  GLstencil *s;
942 
943  if (ctx->Buffer->Stencil) {
944  s = STENCIL_ADDRESS( x, y );
945  MEMCPY( stencil, s, n * sizeof(GLubyte) );
946  }
947 }
948 
949 
950 
951 /*
952  * Write a span of stencil values to the stencil buffer.
953  * Input: n - how many pixels
954  * x,y - location of first pixel
955  * stencil - the array of stencil values
956  */
958  GLuint n, GLint x, GLint y,
959  const GLubyte stencil[] )
960 {
961  GLstencil *s;
962 
963  if (ctx->Buffer->Stencil) {
964  s = STENCIL_ADDRESS( x, y );
965  MEMCPY( s, stencil, n * sizeof(GLubyte) );
966  }
967 }
968 
969 
970 
971 /*
972  * Allocate a new stencil buffer. If there's an old one it will be
973  * deallocated first. The new stencil buffer will be uninitialized.
974  */
976 {
977  GLuint buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
978 
979  /* deallocate current stencil buffer if present */
980  if (ctx->Buffer->Stencil) {
981  free(ctx->Buffer->Stencil);
982  ctx->Buffer->Stencil = NULL;
983  }
984 
985  /* allocate new stencil buffer */
986  ctx->Buffer->Stencil = (GLstencil *) malloc(buffersize * sizeof(GLstencil));
987  if (!ctx->Buffer->Stencil) {
988  /* out of memory */
989  ctx->Stencil.Enabled = GL_FALSE;
990  gl_error( ctx, GL_OUT_OF_MEMORY, "gl_alloc_stencil_buffer" );
991  }
992 }
993 
994 
995 
996 
997 /*
998  * Clear the stencil buffer. If the stencil buffer doesn't exist yet we'll
999  * allocate it now.
1000  */
1002 {
1003  if (ctx->Visual->StencilBits==0 || !ctx->Buffer->Stencil) {
1004  /* no stencil buffer */
1005  return;
1006  }
1007 
1008  if (ctx->Scissor.Enabled) {
1009  /* clear scissor region only */
1010  GLint y;
1011  GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
1012  for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
1013  GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );
1014  MEMSET( ptr, ctx->Stencil.Clear, width * sizeof(GLstencil) );
1015  }
1016  }
1017  else {
1018  /* clear whole stencil buffer */
1019  MEMSET( ctx->Buffer->Stencil, ctx->Stencil.Clear,
1020  ctx->Buffer->Width * ctx->Buffer->Height * sizeof(GLstencil) );
1021  }
1022 }
static void apply_stencil_op_to_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLenum oper, GLubyte mask[])
Definition: stencil.c:207
GLenum func
Definition: glext.h:6028
void gl_write_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, const GLubyte stencil[])
Definition: stencil.c:957
#define MEMSET(DST, VAL, N)
Definition: macros.h:241
GLint GLint GLsizei width
Definition: gl.h:1546
#define GL_LEQUAL
Definition: gl.h:296
void gl_alloc_stencil_buffer(GLcontext *ctx)
Definition: stencil.c:975
GLframebuffer * Buffer
Definition: types.h:1273
GLstencil * Stencil
Definition: types.h:1184
unsigned char GLubyte
Definition: gl.h:157
GLubyte GLstencil
Definition: types.h:208
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
#define GL_FALSE
Definition: gl.h:173
void gl_depth_stencil_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], const GLdepth z[], GLubyte mask[])
Definition: stencil.c:882
GLint Ymin
Definition: types.h:1195
#define free
Definition: debug_ros.c:5
void gl_StencilOp(GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass)
Definition: stencil.c:127
GLdouble n
Definition: glext.h:7729
#define GL_GEQUAL
Definition: gl.h:299
GLint GLint GLint GLint GLint x
Definition: gl.h:1548
GLvisual * Visual
Definition: types.h:1272
GLint Height
Definition: types.h:1179
Definition: send.c:47
#define GL_LESS
Definition: gl.h:294
#define INSIDE_BEGIN_END(CTX)
Definition: macros.h:135
GLint GLfloat GLint stencil
Definition: glext.h:6260
#define STENCIL_BITS
Definition: config.h:152
GLint gl_stencil_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLubyte mask[])
Definition: stencil.c:702
#define STENCIL_ADDRESS(X, Y)
Definition: stencil.c:70
struct dd_function_table Driver
Definition: types.h:1276
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
GLenum GLint GLuint mask
Definition: glext.h:6028
#define GL_INCR
Definition: gl.h:461
#define CLAMP(f, min, max)
Definition: tif_color.c:177
#define GL_ZERO
Definition: gl.h:374
GLenum GLint ref
Definition: glext.h:6028
static PVOID ptr
Definition: dispmode.c:27
GLdouble GLdouble z
Definition: glext.h:5874
smooth NULL
Definition: ftsmooth.c:416
Definition: bufpool.h:45
GLint Xmin
Definition: types.h:1195
#define GL_INVERT
Definition: gl.h:435
#define GL_NOTEQUAL
Definition: gl.h:298
struct gl_scissor_attrib Scissor
Definition: types.h:1332
#define GL_ALWAYS
Definition: gl.h:300
GLint GLdepth
Definition: types.h:218
#define GL_GREATER
Definition: gl.h:297
#define MAX_WIDTH
Definition: config.h:130
#define MEMCPY(DST, SRC, BYTES)
Definition: macros.h:231
GLint gl_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte mask[])
Definition: stencil.c:339
void gl_read_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, GLubyte stencil[])
Definition: stencil.c:938
GLint StencilBits
Definition: types.h:1162
#define GL_NEVER
Definition: gl.h:293
#define GL_INVALID_OPERATION
Definition: gl.h:696
#define GL_REPLACE
Definition: gl.h:460
static void apply_stencil_op_to_pixels(GLcontext *ctx, GLuint n, const GLint x[], const GLint y[], GLenum oper, GLubyte mask[])
Definition: stencil.c:570
void gl_clear_stencil_buffer(GLcontext *ctx)
Definition: stencil.c:1001
GLdouble s
Definition: gl.h:2039
unsigned int GLenum
Definition: gl.h:150
void gl_problem(const GLcontext *ctx, const char *s)
Definition: context.c:1394
void gl_error(GLcontext *ctx, GLenum error, const char *s)
Definition: context.c:1421
#define GL_KEEP
Definition: gl.h:459
struct gl_depthbuffer_attrib Depth
Definition: types.h:1321
unsigned int GLuint
Definition: gl.h:159
void gl_StencilMask(GLcontext *ctx, GLuint mask)
Definition: stencil.c:116
void gl_StencilFunc(GLcontext *ctx, GLenum func, GLint ref, GLuint mask)
Definition: stencil.c:84
struct gl_stencil_attrib Stencil
Definition: types.h:1333
#define GL_INVALID_ENUM
Definition: gl.h:694
void gl_depth_stencil_span(GLcontext *ctx, GLuint n, GLint x, GLint y, const GLdepth z[], GLubyte mask[])
Definition: stencil.c:514
GLint GLint GLint GLint GLint GLint y
Definition: gl.h:1548
GLint Width
Definition: types.h:1178
#define GL_OUT_OF_MEMORY
Definition: gl.h:699
void gl_ClearStencil(GLcontext *ctx, GLint s)
Definition: stencil.c:73
int GLint
Definition: gl.h:156
#define malloc
Definition: debug_ros.c:4
GLint Xmax
Definition: types.h:1195
#define PB_SIZE
Definition: pb.h:52
#define GL_EQUAL
Definition: gl.h:295
#define GL_DECR
Definition: gl.h:462