2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
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:
14 * The above copyright notice and this permission notice shall be included
15 * in all copies or substantial portions of the Software.
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.
26 #include "main/glheader.h"
27 #include "main/context.h"
28 #include "main/imports.h"
30 #include "s_context.h"
32 #include "s_stencil.h"
39 IF stencil test fails THEN
40 Apply fail-op to stencil value
41 Don't write the pixel (RGBA,Z)
43 IF doing depth test && depth test fails THEN
44 Apply zfail-op to stencil value
45 Write RGBA and Z to appropriate buffers
47 Apply zpass-op to stencil value
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
64 apply_stencil_op( const GLcontext
*ctx
, GLenum oper
, GLuint face
,
65 GLuint n
, GLstencil stencil
[], const GLubyte mask
[] )
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;
88 stencil
[i
] = (GLstencil
) (stencil
[i
] & invmask
);
104 GLstencil s
= stencil
[i
];
105 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& ref
));
114 GLstencil s
= stencil
[i
];
115 if (s
< stencilMax
) {
116 stencil
[i
] = (GLstencil
) (s
+1);
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)));
137 GLstencil s
= stencil
[i
];
139 stencil
[i
] = (GLstencil
) (s
-1);
147 /* VERIFY logic of subtracting 1 to a write-masked value */
148 GLstencil s
= stencil
[i
];
150 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& (s
-1)));
156 case GL_INCR_WRAP_EXT
:
167 GLstencil s
= stencil
[i
];
168 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& (s
+1)));
173 case GL_DECR_WRAP_EXT
:
184 GLstencil s
= stencil
[i
];
185 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& (s
-1)));
194 GLstencil s
= stencil
[i
];
195 stencil
[i
] = (GLstencil
) ~s
;
202 GLstencil s
= stencil
[i
];
203 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& ~s
));
209 _mesa_problem(ctx
, "Bad stencil op in apply_stencil_op");
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.
228 do_stencil_test( GLcontext
*ctx
, GLuint face
, GLuint n
, GLstencil stencil
[],
231 GLubyte fail
[MAX_WIDTH
];
232 GLboolean allfail
= GL_FALSE
;
235 const GLuint valueMask
= ctx
->Stencil
.ValueMask
[face
];
237 ASSERT(n
<= MAX_WIDTH
);
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
245 * the stencil fail operator is not to be applied
248 switch (ctx
->Stencil
.Function
[face
]) {
250 /* never pass; always fail */
263 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
266 s
= (GLstencil
) (stencil
[i
] & valueMask
);
282 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
285 s
= (GLstencil
) (stencil
[i
] & valueMask
);
301 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
304 s
= (GLstencil
) (stencil
[i
] & valueMask
);
320 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
323 s
= (GLstencil
) (stencil
[i
] & valueMask
);
339 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
342 s
= (GLstencil
) (stencil
[i
] & valueMask
);
358 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
361 s
= (GLstencil
) (stencil
[i
] & valueMask
);
383 _mesa_problem(ctx
, "Bad stencil func in gl_stencil_span");
387 if (ctx
->Stencil
.FailFunc
[face
] != GL_KEEP
) {
388 apply_stencil_op( ctx
, ctx
->Stencil
.FailFunc
[face
], face
, n
, stencil
, fail
);
396 * Compute the zpass/zfail masks by comparing the pre- and post-depth test
400 compute_pass_fail_masks(GLuint n
, const GLubyte origMask
[],
401 const GLubyte newMask
[],
402 GLubyte passMask
[], GLubyte failMask
[])
405 for (i
= 0; i
< n
; i
++) {
406 ASSERT(newMask
[i
] == 0 || newMask
[i
] == 1);
407 passMask
[i
] = origMask
[i
] & newMask
[i
];
408 failMask
[i
] = origMask
[i
] & (newMask
[i
] ^ 1);
414 * Apply stencil and depth testing to the span of pixels.
415 * Both software and hardware stencil buffers are acceptable.
416 * Input: n - number of pixels in the span
417 * x, y - location of leftmost pixel in span
418 * z - array [n] of z values
419 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
420 * Output: mask - array [n] of flags (1=stencil and depth test passed)
421 * Return: GL_FALSE - all fragments failed the testing
422 * GL_TRUE - one or more fragments passed the testing
426 stencil_and_ztest_span(GLcontext
*ctx
, SWspan
*span
, GLuint face
)
428 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
429 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
430 GLstencil stencilRow
[MAX_WIDTH
];
432 const GLuint n
= span
->end
;
433 const GLint x
= span
->x
;
434 const GLint y
= span
->y
;
435 GLubyte
*mask
= span
->array
->mask
;
437 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
438 ASSERT(ctx
->Stencil
.Enabled
);
439 ASSERT(n
<= MAX_WIDTH
);
441 if (ctx
->Depth
.Test
) {
442 ASSERT(span
->arrayMask
& SPAN_Z
);
446 stencil
= (GLstencil
*) rb
->GetPointer(ctx
, rb
, x
, y
);
448 rb
->GetRow(ctx
, rb
, n
, x
, y
, stencilRow
);
449 stencil
= stencilRow
;
453 * Apply the stencil test to the fragments.
454 * failMask[i] is 1 if the stencil test failed.
456 if (do_stencil_test( ctx
, face
, n
, stencil
, mask
) == GL_FALSE
) {
457 /* all fragments failed the stencil test, we're done. */
458 span
->writeAll
= GL_FALSE
;
459 if (!rb
->GetPointer(ctx
, rb
, 0, 0)) {
460 /* put updated stencil values into buffer */
461 rb
->PutRow(ctx
, rb
, n
, x
, y
, stencil
, NULL
);
467 * Some fragments passed the stencil test, apply depth test to them
468 * and apply Zpass and Zfail stencil ops.
470 if (ctx
->Depth
.Test
== GL_FALSE
) {
472 * No depth buffer, just apply zpass stencil function to active pixels.
474 apply_stencil_op( ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
, n
, stencil
, mask
);
478 * Perform depth buffering, then apply zpass or zfail stencil function.
480 GLubyte passMask
[MAX_WIDTH
], failMask
[MAX_WIDTH
], origMask
[MAX_WIDTH
];
482 /* save the current mask bits */
483 _mesa_memcpy(origMask
, mask
, n
* sizeof(GLubyte
));
485 /* apply the depth test */
486 _swrast_depth_test_span(ctx
, span
);
488 compute_pass_fail_masks(n
, origMask
, mask
, passMask
, failMask
);
490 /* apply the pass and fail operations */
491 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
492 apply_stencil_op( ctx
, ctx
->Stencil
.ZFailFunc
[face
], face
,
493 n
, stencil
, failMask
);
495 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
496 apply_stencil_op( ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
497 n
, stencil
, passMask
);
502 * Write updated stencil values back into hardware stencil buffer.
504 if (!rb
->GetPointer(ctx
, rb
, 0, 0)) {
505 rb
->PutRow(ctx
, rb
, n
, x
, y
, stencil
, NULL
);
508 span
->writeAll
= GL_FALSE
;
510 return GL_TRUE
; /* one or more fragments passed both tests */
516 * Return the address of a stencil buffer value given the window coords:
518 #define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
523 * Apply the given stencil operator for each pixel in the array whose
525 * \note This is for software stencil buffers only.
526 * Input: n - number of pixels in the span
527 * x, y - array of [n] pixels
528 * operator - the stencil buffer operator
529 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
532 apply_stencil_op_to_pixels( GLcontext
*ctx
,
533 GLuint n
, const GLint x
[], const GLint y
[],
534 GLenum oper
, GLuint face
, const GLubyte mask
[] )
536 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
537 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
538 const GLstencil stencilMax
= (1 << fb
->Visual
.stencilBits
) - 1;
539 const GLstencil ref
= ctx
->Stencil
.Ref
[face
];
540 const GLstencil wrtmask
= ctx
->Stencil
.WriteMask
[face
];
541 const GLstencil invmask
= (GLstencil
) (~wrtmask
);
543 GLstencil
*stencilStart
= (GLubyte
*) rb
->Data
;
544 const GLuint stride
= rb
->Width
;
546 ASSERT(rb
->GetPointer(ctx
, rb
, 0, 0));
547 ASSERT(sizeof(GLstencil
) == 1);
557 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
565 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
566 *sptr
= (GLstencil
) (invmask
& *sptr
);
575 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
583 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
584 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& ref
));
593 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
594 if (*sptr
< stencilMax
) {
595 *sptr
= (GLstencil
) (*sptr
+ 1);
603 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
604 if (*sptr
< stencilMax
) {
605 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
+1)));
615 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
617 *sptr
= (GLstencil
) (*sptr
- 1);
625 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
627 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
-1)));
633 case GL_INCR_WRAP_EXT
:
637 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
638 *sptr
= (GLstencil
) (*sptr
+ 1);
645 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
646 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
+1)));
651 case GL_DECR_WRAP_EXT
:
655 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
656 *sptr
= (GLstencil
) (*sptr
- 1);
663 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
664 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
-1)));
673 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
674 *sptr
= (GLstencil
) (~*sptr
);
681 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
682 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& ~*sptr
));
688 _mesa_problem(ctx
, "Bad stencilop in apply_stencil_op_to_pixels");
695 * Apply stencil test to an array of pixels before depth buffering.
697 * \note Used for software stencil buffer only.
698 * Input: n - number of pixels in the span
699 * x, y - array of [n] pixels to stencil
700 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
701 * Output: mask - pixels which fail the stencil test will have their
702 * mask flag set to 0.
703 * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
706 stencil_test_pixels( GLcontext
*ctx
, GLuint face
, GLuint n
,
707 const GLint x
[], const GLint y
[], GLubyte mask
[] )
709 const struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
710 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
711 GLubyte fail
[MAX_WIDTH
];
714 GLboolean allfail
= GL_FALSE
;
715 const GLuint valueMask
= ctx
->Stencil
.ValueMask
[face
];
716 const GLstencil
*stencilStart
= (GLstencil
*) rb
->Data
;
717 const GLuint stride
= rb
->Width
;
719 ASSERT(rb
->GetPointer(ctx
, rb
, 0, 0));
720 ASSERT(sizeof(GLstencil
) == 1);
723 * Perform stencil test. The results of this operation are stored
724 * in the fail[] array:
725 * IF fail[i] is non-zero THEN
726 * the stencil fail operator is to be applied
728 * the stencil fail operator is not to be applied
732 switch (ctx
->Stencil
.Function
[face
]) {
747 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
750 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
751 s
= (GLstencil
) (*sptr
& valueMask
);
767 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
770 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
771 s
= (GLstencil
) (*sptr
& valueMask
);
787 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
790 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
791 s
= (GLstencil
) (*sptr
& valueMask
);
807 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
810 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
811 s
= (GLstencil
) (*sptr
& valueMask
);
827 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
830 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
831 s
= (GLstencil
) (*sptr
& valueMask
);
847 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
850 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
851 s
= (GLstencil
) (*sptr
& valueMask
);
873 _mesa_problem(ctx
, "Bad stencil func in gl_stencil_pixels");
877 if (ctx
->Stencil
.FailFunc
[face
] != GL_KEEP
) {
878 apply_stencil_op_to_pixels( ctx
, n
, x
, y
, ctx
->Stencil
.FailFunc
[face
],
889 * Apply stencil and depth testing to an array of pixels.
890 * This is used both for software and hardware stencil buffers.
892 * The comments in this function are a bit sparse but the code is
893 * almost identical to stencil_and_ztest_span(), which is well
896 * Input: n - number of pixels in the array
897 * x, y - array of [n] pixel positions
898 * z - array [n] of z values
899 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
900 * Output: mask - array [n] of flags (1=stencil and depth test passed)
901 * Return: GL_FALSE - all fragments failed the testing
902 * GL_TRUE - one or more fragments passed the testing
905 stencil_and_ztest_pixels( GLcontext
*ctx
, SWspan
*span
, GLuint face
)
907 GLubyte passMask
[MAX_WIDTH
], failMask
[MAX_WIDTH
], origMask
[MAX_WIDTH
];
908 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
909 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
910 const GLuint n
= span
->end
;
911 const GLint
*x
= span
->array
->x
;
912 const GLint
*y
= span
->array
->y
;
913 GLubyte
*mask
= span
->array
->mask
;
915 ASSERT(span
->arrayMask
& SPAN_XY
);
916 ASSERT(ctx
->Stencil
.Enabled
);
917 ASSERT(n
<= MAX_WIDTH
);
919 if (!rb
->GetPointer(ctx
, rb
, 0, 0)) {
920 /* No direct access */
921 GLstencil stencil
[MAX_WIDTH
];
923 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
924 _swrast_get_values(ctx
, rb
, n
, x
, y
, stencil
, sizeof(GLubyte
));
926 _mesa_memcpy(origMask
, mask
, n
* sizeof(GLubyte
));
928 (void) do_stencil_test(ctx
, face
, n
, stencil
, mask
);
930 if (ctx
->Depth
.Test
== GL_FALSE
) {
931 apply_stencil_op(ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
935 GLubyte tmpMask
[MAX_WIDTH
];
936 _mesa_memcpy(tmpMask
, mask
, n
* sizeof(GLubyte
));
938 _swrast_depth_test_span(ctx
, span
);
940 compute_pass_fail_masks(n
, tmpMask
, mask
, passMask
, failMask
);
942 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
943 apply_stencil_op(ctx
, ctx
->Stencil
.ZFailFunc
[face
], face
,
944 n
, stencil
, failMask
);
946 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
947 apply_stencil_op(ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
948 n
, stencil
, passMask
);
952 /* Write updated stencil values into hardware stencil buffer */
953 rb
->PutValues(ctx
, rb
, n
, x
, y
, stencil
, origMask
);
958 /* Direct access to stencil buffer */
960 if (stencil_test_pixels(ctx
, face
, n
, x
, y
, mask
) == GL_FALSE
) {
961 /* all fragments failed the stencil test, we're done. */
965 if (ctx
->Depth
.Test
==GL_FALSE
) {
966 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
967 ctx
->Stencil
.ZPassFunc
[face
], face
, mask
);
970 _mesa_memcpy(origMask
, mask
, n
* sizeof(GLubyte
));
972 _swrast_depth_test_span(ctx
, span
);
974 compute_pass_fail_masks(n
, origMask
, mask
, passMask
, failMask
);
976 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
977 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
978 ctx
->Stencil
.ZFailFunc
[face
],
981 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
982 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
983 ctx
->Stencil
.ZPassFunc
[face
],
988 return GL_TRUE
; /* one or more fragments passed both tests */
994 * /return GL_TRUE = one or more fragments passed,
995 * GL_FALSE = all fragments failed.
998 _swrast_stencil_and_ztest_span(GLcontext
*ctx
, SWspan
*span
)
1000 if (span
->arrayMask
& SPAN_XY
)
1001 return stencil_and_ztest_pixels(ctx
, span
, span
->facing
);
1003 return stencil_and_ztest_span(ctx
, span
, span
->facing
);
1009 clip_span(GLuint bufferWidth
, GLuint bufferHeight
,
1010 GLint x
, GLint y
, GLuint
*count
)
1013 GLuint skipPixels
= 0;
1015 if (y
< 0 || y
>= bufferHeight
|| x
+ n
<= 0 || x
>= bufferWidth
) {
1016 /* totally out of bounds */
1027 if (x
+ n
> bufferWidth
) {
1028 GLint dx
= x
+ n
- bufferWidth
;
1041 * Return a span of stencil values from the stencil buffer.
1042 * Used for glRead/CopyPixels
1043 * Input: n - how many pixels
1044 * x,y - location of first pixel
1045 * Output: stencil - the array of stencil values
1048 _swrast_read_stencil_span(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1049 GLint n
, GLint x
, GLint y
, GLstencil stencil
[])
1051 if (y
< 0 || y
>= (GLint
) rb
->Height
||
1052 x
+ n
<= 0 || x
>= (GLint
) rb
->Width
) {
1053 /* span is completely outside framebuffer */
1054 return; /* undefined values OK */
1063 if (x
+ n
> (GLint
) rb
->Width
) {
1064 GLint dx
= x
+ n
- rb
->Width
;
1071 rb
->GetRow(ctx
, rb
, n
, x
, y
, stencil
);
1077 * Write a span of stencil values to the stencil buffer. This function
1078 * applies the stencil write mask when needed.
1079 * Used for glDraw/CopyPixels
1080 * Input: n - how many pixels
1081 * x, y - location of first pixel
1082 * stencil - the array of stencil values
1085 _swrast_write_stencil_span(GLcontext
*ctx
, GLint n
, GLint x
, GLint y
,
1086 const GLstencil stencil
[] )
1088 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1089 struct gl_renderbuffer
*rb
= fb
->_StencilBuffer
;
1090 const GLuint stencilMax
= (1 << fb
->Visual
.stencilBits
) - 1;
1091 const GLuint stencilMask
= ctx
->Stencil
.WriteMask
[0];
1093 if (y
< 0 || y
>= (GLint
) rb
->Height
||
1094 x
+ n
<= 0 || x
>= (GLint
) rb
->Width
) {
1095 /* span is completely outside framebuffer */
1096 return; /* undefined values OK */
1104 if (x
+ n
> (GLint
) rb
->Width
) {
1105 GLint dx
= x
+ n
- rb
->Width
;
1112 if ((stencilMask
& stencilMax
) != stencilMax
) {
1113 /* need to apply writemask */
1114 GLstencil destVals
[MAX_WIDTH
], newVals
[MAX_WIDTH
];
1116 rb
->GetRow(ctx
, rb
, n
, x
, y
, destVals
);
1117 for (i
= 0; i
< n
; i
++) {
1119 = (stencil
[i
] & stencilMask
) | (destVals
[i
] & ~stencilMask
);
1121 rb
->PutRow(ctx
, rb
, n
, x
, y
, newVals
, NULL
);
1124 rb
->PutRow(ctx
, rb
, n
, x
, y
, stencil
, NULL
);
1131 * Clear the stencil buffer.
1134 _swrast_clear_stencil_buffer( GLcontext
*ctx
, struct gl_renderbuffer
*rb
)
1136 const GLubyte stencilBits
= ctx
->DrawBuffer
->Visual
.stencilBits
;
1137 const GLuint mask
= ctx
->Stencil
.WriteMask
[0];
1138 const GLuint invMask
= ~mask
;
1139 const GLuint clearVal
= (ctx
->Stencil
.Clear
& mask
);
1140 const GLuint stencilMax
= (1 << stencilBits
) - 1;
1141 GLint x
, y
, width
, height
;
1143 if (!rb
|| mask
== 0)
1146 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
||
1147 rb
->DataType
== GL_UNSIGNED_SHORT
);
1149 ASSERT(rb
->_BaseFormat
== GL_STENCIL_INDEX
);
1151 /* compute region to clear */
1152 x
= ctx
->DrawBuffer
->_Xmin
;
1153 y
= ctx
->DrawBuffer
->_Ymin
;
1154 width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
1155 height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
1157 if (rb
->GetPointer(ctx
, rb
, 0, 0)) {
1158 /* Direct buffer access */
1159 if ((mask
& stencilMax
) != stencilMax
) {
1160 /* need to mask the clear */
1161 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1163 for (i
= 0; i
< height
; i
++) {
1164 GLubyte
*stencil
= (GLubyte
*) rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1165 for (j
= 0; j
< width
; j
++) {
1166 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1172 for (i
= 0; i
< height
; i
++) {
1173 GLushort
*stencil
= (GLushort
*) rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1174 for (j
= 0; j
< width
; j
++) {
1175 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1181 /* no bit masking */
1182 if (width
== (GLint
) rb
->Width
&& rb
->DataType
== GL_UNSIGNED_BYTE
) {
1183 /* optimized case */
1184 /* Note: bottom-to-top raster assumed! */
1185 GLubyte
*stencil
= (GLubyte
*) rb
->GetPointer(ctx
, rb
, x
, y
);
1186 GLuint len
= width
* height
* sizeof(GLubyte
);
1187 _mesa_memset(stencil
, clearVal
, len
);
1192 for (i
= 0; i
< height
; i
++) {
1193 GLvoid
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1194 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1195 _mesa_memset(stencil
, clearVal
, width
);
1198 _mesa_memset16((short unsigned int*) stencil
, clearVal
, width
);
1205 /* no direct access */
1206 if ((mask
& stencilMax
) != stencilMax
) {
1207 /* need to mask the clear */
1208 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1210 for (i
= 0; i
< height
; i
++) {
1211 GLubyte stencil
[MAX_WIDTH
];
1212 rb
->GetRow(ctx
, rb
, width
, x
, y
+ i
, stencil
);
1213 for (j
= 0; j
< width
; j
++) {
1214 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1216 rb
->PutRow(ctx
, rb
, width
, x
, y
+ i
, stencil
, NULL
);
1221 for (i
= 0; i
< height
; i
++) {
1222 GLushort stencil
[MAX_WIDTH
];
1223 rb
->GetRow(ctx
, rb
, width
, x
, y
+ i
, stencil
);
1224 for (j
= 0; j
< width
; j
++) {
1225 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1227 rb
->PutRow(ctx
, rb
, width
, x
, y
+ i
, stencil
, NULL
);
1232 /* no bit masking */
1233 const GLubyte clear8
= (GLubyte
) clearVal
;
1234 const GLushort clear16
= (GLushort
) clearVal
;
1237 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1243 for (i
= 0; i
< height
; i
++) {
1244 rb
->PutMonoRow(ctx
, rb
, width
, x
, y
+ i
, clear
, NULL
);