2 * Mesa 3-D graphics library
5 * Copyright (C) 1999-2005 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.
32 #include "s_context.h"
34 #include "s_stencil.h"
41 IF stencil test fails THEN
42 Apply fail-op to stencil value
43 Don't write the pixel (RGBA,Z)
45 IF doing depth test && depth test fails THEN
46 Apply zfail-op to stencil value
47 Write RGBA and Z to appropriate buffers
49 Apply zpass-op to stencil value
56 * Apply the given stencil operator to the array of stencil values.
57 * Don't touch stencil[i] if mask[i] is zero.
58 * Input: n - size of stencil array
59 * oper - the stencil buffer operator
60 * face - 0 or 1 for front or back face operation
61 * stencil - array of stencil values
62 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
63 * Output: stencil - modified values
66 apply_stencil_op( const GLcontext
*ctx
, GLenum oper
, GLuint face
,
67 GLuint n
, GLstencil stencil
[], const GLubyte mask
[] )
69 const GLstencil ref
= ctx
->Stencil
.Ref
[face
];
70 const GLstencil wrtmask
= ctx
->Stencil
.WriteMask
[face
];
71 const GLstencil invmask
= (GLstencil
) (~wrtmask
);
72 const GLstencil stencilMax
= (1 << ctx
->DrawBuffer
->Visual
.stencilBits
) - 1;
90 stencil
[i
] = (GLstencil
) (stencil
[i
] & invmask
);
106 GLstencil s
= stencil
[i
];
107 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& ref
));
116 GLstencil s
= stencil
[i
];
117 if (s
< stencilMax
) {
118 stencil
[i
] = (GLstencil
) (s
+1);
126 /* VERIFY logic of adding 1 to a write-masked value */
127 GLstencil s
= stencil
[i
];
128 if (s
< stencilMax
) {
129 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& (s
+1)));
139 GLstencil s
= stencil
[i
];
141 stencil
[i
] = (GLstencil
) (s
-1);
149 /* VERIFY logic of subtracting 1 to a write-masked value */
150 GLstencil s
= stencil
[i
];
152 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& (s
-1)));
158 case GL_INCR_WRAP_EXT
:
169 GLstencil s
= stencil
[i
];
170 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& (s
+1)));
175 case GL_DECR_WRAP_EXT
:
186 GLstencil s
= stencil
[i
];
187 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& (s
-1)));
196 GLstencil s
= stencil
[i
];
197 stencil
[i
] = (GLstencil
) ~s
;
204 GLstencil s
= stencil
[i
];
205 stencil
[i
] = (GLstencil
) ((invmask
& s
) | (wrtmask
& ~s
));
211 _mesa_problem(ctx
, "Bad stencil op in apply_stencil_op");
219 * Apply stencil test to an array of stencil values (before depth buffering).
220 * Input: face - 0 or 1 for front or back-face polygons
221 * n - number of pixels in the array
222 * stencil - array of [n] stencil values
223 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
224 * Output: mask - pixels which fail the stencil test will have their
225 * mask flag set to 0.
226 * stencil - updated stencil values (where the test passed)
227 * Return: GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
230 do_stencil_test( GLcontext
*ctx
, GLuint face
, GLuint n
, GLstencil stencil
[],
233 GLubyte fail
[MAX_WIDTH
];
234 GLboolean allfail
= GL_FALSE
;
237 const GLuint valueMask
= ctx
->Stencil
.ValueMask
[face
];
239 ASSERT(n
<= MAX_WIDTH
);
242 * Perform stencil test. The results of this operation are stored
243 * in the fail[] array:
244 * IF fail[i] is non-zero THEN
245 * the stencil fail operator is to be applied
247 * the stencil fail operator is not to be applied
250 switch (ctx
->Stencil
.Function
[face
]) {
252 /* never pass; always fail */
265 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
268 s
= (GLstencil
) (stencil
[i
] & valueMask
);
284 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
287 s
= (GLstencil
) (stencil
[i
] & valueMask
);
303 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
306 s
= (GLstencil
) (stencil
[i
] & valueMask
);
322 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
325 s
= (GLstencil
) (stencil
[i
] & valueMask
);
341 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
344 s
= (GLstencil
) (stencil
[i
] & valueMask
);
360 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
363 s
= (GLstencil
) (stencil
[i
] & valueMask
);
385 _mesa_problem(ctx
, "Bad stencil func in gl_stencil_span");
389 if (ctx
->Stencil
.FailFunc
[face
] != GL_KEEP
) {
390 apply_stencil_op( ctx
, ctx
->Stencil
.FailFunc
[face
], face
, n
, stencil
, fail
);
399 * Apply stencil and depth testing to the span of pixels.
400 * Both software and hardware stencil buffers are acceptable.
401 * Input: n - number of pixels in the span
402 * x, y - location of leftmost pixel in span
403 * z - array [n] of z values
404 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
405 * Output: mask - array [n] of flags (1=stencil and depth test passed)
406 * Return: GL_FALSE - all fragments failed the testing
407 * GL_TRUE - one or more fragments passed the testing
411 stencil_and_ztest_span(GLcontext
*ctx
, struct sw_span
*span
, GLuint face
)
413 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
414 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
415 GLstencil stencilRow
[MAX_WIDTH
];
417 const GLuint n
= span
->end
;
418 const GLint x
= span
->x
;
419 const GLint y
= span
->y
;
420 GLubyte
*mask
= span
->array
->mask
;
422 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
423 ASSERT(ctx
->Stencil
.Enabled
);
424 ASSERT(n
<= MAX_WIDTH
);
426 if (ctx
->Depth
.Test
) {
427 ASSERT(span
->arrayMask
& SPAN_Z
);
431 stencil
= rb
->GetPointer(ctx
, rb
, x
, y
);
433 rb
->GetRow(ctx
, rb
, n
, x
, y
, stencilRow
);
434 stencil
= stencilRow
;
438 * Apply the stencil test to the fragments.
439 * failMask[i] is 1 if the stencil test failed.
441 if (do_stencil_test( ctx
, face
, n
, stencil
, mask
) == GL_FALSE
) {
442 /* all fragments failed the stencil test, we're done. */
443 span
->writeAll
= GL_FALSE
;
448 * Some fragments passed the stencil test, apply depth test to them
449 * and apply Zpass and Zfail stencil ops.
451 if (ctx
->Depth
.Test
== GL_FALSE
) {
453 * No depth buffer, just apply zpass stencil function to active pixels.
455 apply_stencil_op( ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
, n
, stencil
, mask
);
459 * Perform depth buffering, then apply zpass or zfail stencil function.
461 GLubyte passmask
[MAX_WIDTH
], failmask
[MAX_WIDTH
], oldmask
[MAX_WIDTH
];
464 /* save the current mask bits */
465 _mesa_memcpy(oldmask
, mask
, n
* sizeof(GLubyte
));
467 /* apply the depth test */
468 _swrast_depth_test_span(ctx
, span
);
470 /* Set the stencil pass/fail flags according to result of depth testing.
471 * if oldmask[i] == 0 then
472 * Don't touch the stencil value
473 * else if oldmask[i] and newmask[i] then
476 * assert(oldmask[i] && !newmask[i])
481 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
482 passmask
[i
] = oldmask
[i
] & mask
[i
];
483 failmask
[i
] = oldmask
[i
] & (mask
[i
] ^ 1);
486 /* apply the pass and fail operations */
487 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
488 apply_stencil_op( ctx
, ctx
->Stencil
.ZFailFunc
[face
], face
,
489 n
, stencil
, failmask
);
491 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
492 apply_stencil_op( ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
493 n
, stencil
, passmask
);
498 * Write updated stencil values back into hardware stencil buffer.
500 if (!rb
->GetPointer(ctx
, rb
, 0, 0)) {
501 rb
->PutRow(ctx
, rb
, n
, x
, y
, stencil
, mask
);
504 span
->writeAll
= GL_FALSE
;
506 return GL_TRUE
; /* one or more fragments passed both tests */
512 * Return the address of a stencil buffer value given the window coords:
514 #define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
519 * Apply the given stencil operator for each pixel in the array whose
521 * \note This is for software stencil buffers only.
522 * Input: n - number of pixels in the span
523 * x, y - array of [n] pixels
524 * operator - the stencil buffer operator
525 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
528 apply_stencil_op_to_pixels( GLcontext
*ctx
,
529 GLuint n
, const GLint x
[], const GLint y
[],
530 GLenum oper
, GLuint face
, const GLubyte mask
[] )
532 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
533 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
534 const GLstencil stencilMax
= (1 << fb
->Visual
.stencilBits
) - 1;
535 const GLstencil ref
= ctx
->Stencil
.Ref
[face
];
536 const GLstencil wrtmask
= ctx
->Stencil
.WriteMask
[face
];
537 const GLstencil invmask
= (GLstencil
) (~wrtmask
);
539 GLstencil
*stencilStart
= (GLubyte
*) rb
->Data
;
540 const GLuint stride
= rb
->Width
;
542 ASSERT(rb
->GetPointer(ctx
, rb
, 0, 0));
543 ASSERT(sizeof(GLstencil
) == 1);
553 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
561 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
562 *sptr
= (GLstencil
) (invmask
& *sptr
);
571 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
579 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
580 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& ref
));
589 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
590 if (*sptr
< stencilMax
) {
591 *sptr
= (GLstencil
) (*sptr
+ 1);
599 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
600 if (*sptr
< stencilMax
) {
601 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
+1)));
611 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
613 *sptr
= (GLstencil
) (*sptr
- 1);
621 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
623 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
-1)));
629 case GL_INCR_WRAP_EXT
:
633 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
634 *sptr
= (GLstencil
) (*sptr
+ 1);
641 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
642 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
+1)));
647 case GL_DECR_WRAP_EXT
:
651 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
652 *sptr
= (GLstencil
) (*sptr
- 1);
659 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
660 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
-1)));
669 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
670 *sptr
= (GLstencil
) (~*sptr
);
677 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
678 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& ~*sptr
));
684 _mesa_problem(ctx
, "Bad stencilop in apply_stencil_op_to_pixels");
691 * Apply stencil test to an array of pixels before depth buffering.
693 * \note Used for software stencil buffer only.
694 * Input: n - number of pixels in the span
695 * x, y - array of [n] pixels to stencil
696 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
697 * Output: mask - pixels which fail the stencil test will have their
698 * mask flag set to 0.
699 * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
702 stencil_test_pixels( GLcontext
*ctx
, GLuint face
, GLuint n
,
703 const GLint x
[], const GLint y
[], GLubyte mask
[] )
705 const struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
706 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
707 GLubyte fail
[MAX_WIDTH
];
710 GLboolean allfail
= GL_FALSE
;
711 const GLuint valueMask
= ctx
->Stencil
.ValueMask
[face
];
712 const GLstencil
*stencilStart
= (GLstencil
*) rb
->Data
;
713 const GLuint stride
= rb
->Width
;
715 ASSERT(rb
->GetPointer(ctx
, rb
, 0, 0));
716 ASSERT(sizeof(GLstencil
) == 1);
719 * Perform stencil test. The results of this operation are stored
720 * in the fail[] array:
721 * IF fail[i] is non-zero THEN
722 * the stencil fail operator is to be applied
724 * the stencil fail operator is not to be applied
728 switch (ctx
->Stencil
.Function
[face
]) {
743 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
746 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
747 s
= (GLstencil
) (*sptr
& valueMask
);
763 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
766 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
767 s
= (GLstencil
) (*sptr
& valueMask
);
783 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
786 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
787 s
= (GLstencil
) (*sptr
& valueMask
);
803 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
806 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
807 s
= (GLstencil
) (*sptr
& valueMask
);
823 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
826 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
827 s
= (GLstencil
) (*sptr
& valueMask
);
843 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
846 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
847 s
= (GLstencil
) (*sptr
& valueMask
);
869 _mesa_problem(ctx
, "Bad stencil func in gl_stencil_pixels");
873 if (ctx
->Stencil
.FailFunc
[face
] != GL_KEEP
) {
874 apply_stencil_op_to_pixels( ctx
, n
, x
, y
, ctx
->Stencil
.FailFunc
[face
],
885 * Apply stencil and depth testing to an array of pixels.
886 * This is used both for software and hardware stencil buffers.
888 * The comments in this function are a bit sparse but the code is
889 * almost identical to stencil_and_ztest_span(), which is well
892 * Input: n - number of pixels in the array
893 * x, y - array of [n] pixel positions
894 * z - array [n] of z values
895 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
896 * Output: mask - array [n] of flags (1=stencil and depth test passed)
897 * Return: GL_FALSE - all fragments failed the testing
898 * GL_TRUE - one or more fragments passed the testing
901 stencil_and_ztest_pixels( GLcontext
*ctx
, struct sw_span
*span
, GLuint face
)
903 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
904 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
905 const GLuint n
= span
->end
;
906 const GLint
*x
= span
->array
->x
;
907 const GLint
*y
= span
->array
->y
;
908 GLubyte
*mask
= span
->array
->mask
;
910 ASSERT(span
->arrayMask
& SPAN_XY
);
911 ASSERT(ctx
->Stencil
.Enabled
);
912 ASSERT(n
<= MAX_WIDTH
);
914 if (!rb
->GetPointer(ctx
, rb
, 0, 0)) {
915 /* No direct access */
916 GLstencil stencil
[MAX_WIDTH
];
917 GLubyte origMask
[MAX_WIDTH
];
919 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
920 _swrast_get_values(ctx
, rb
, n
, x
, y
, stencil
, sizeof(GLubyte
));
922 _mesa_memcpy(origMask
, mask
, n
* sizeof(GLubyte
));
924 (void) do_stencil_test(ctx
, face
, n
, stencil
, mask
);
926 if (ctx
->Depth
.Test
== GL_FALSE
) {
927 apply_stencil_op(ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
931 _swrast_depth_test_span(ctx
, span
);
933 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
934 GLubyte failmask
[MAX_WIDTH
];
936 for (i
= 0; i
< n
; i
++) {
937 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
938 failmask
[i
] = origMask
[i
] & (mask
[i
] ^ 1);
940 apply_stencil_op(ctx
, ctx
->Stencil
.ZFailFunc
[face
], face
,
941 n
, stencil
, failmask
);
943 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
944 GLubyte passmask
[MAX_WIDTH
];
946 for (i
= 0; i
< n
; i
++) {
947 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
948 passmask
[i
] = origMask
[i
] & mask
[i
];
950 apply_stencil_op(ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
951 n
, stencil
, passmask
);
955 /* Write updated stencil values into hardware stencil buffer */
956 rb
->PutValues(ctx
, rb
, n
, x
, y
, stencil
, origMask
);
961 /* Direct access to stencil buffer */
963 if (stencil_test_pixels(ctx
, face
, n
, x
, y
, mask
) == GL_FALSE
) {
964 /* all fragments failed the stencil test, we're done. */
968 if (ctx
->Depth
.Test
==GL_FALSE
) {
969 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
970 ctx
->Stencil
.ZPassFunc
[face
], face
, mask
);
973 GLubyte passmask
[MAX_WIDTH
], failmask
[MAX_WIDTH
], oldmask
[MAX_WIDTH
];
976 _mesa_memcpy(oldmask
, mask
, n
* sizeof(GLubyte
));
978 _swrast_depth_test_span(ctx
, span
);
981 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
982 passmask
[i
] = oldmask
[i
] & mask
[i
];
983 failmask
[i
] = oldmask
[i
] & (mask
[i
] ^ 1);
986 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
987 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
988 ctx
->Stencil
.ZFailFunc
[face
],
991 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
992 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
993 ctx
->Stencil
.ZPassFunc
[face
],
998 return GL_TRUE
; /* one or more fragments passed both tests */
1004 * /return GL_TRUE = one or more fragments passed,
1005 * GL_FALSE = all fragments failed.
1008 _swrast_stencil_and_ztest_span(GLcontext
*ctx
, struct sw_span
*span
)
1010 /* span->facing can only be non-zero if using two-sided stencil */
1011 ASSERT(ctx
->Stencil
._TestTwoSide
|| span
->facing
== 0);
1012 if (span
->arrayMask
& SPAN_XY
)
1013 return stencil_and_ztest_pixels(ctx
, span
, span
->facing
);
1015 return stencil_and_ztest_span(ctx
, span
, span
->facing
);
1021 clip_span(GLuint bufferWidth
, GLuint bufferHeight
,
1022 GLint x
, GLint y
, GLuint
*count
)
1025 GLuint skipPixels
= 0;
1027 if (y
< 0 || y
>= bufferHeight
|| x
+ n
<= 0 || x
>= bufferWidth
) {
1028 /* totally out of bounds */
1039 if (x
+ n
> bufferWidth
) {
1040 GLint dx
= x
+ n
- bufferWidth
;
1053 * Return a span of stencil values from the stencil buffer.
1054 * Used for glRead/CopyPixels
1055 * Input: n - how many pixels
1056 * x,y - location of first pixel
1057 * Output: stencil - the array of stencil values
1060 _swrast_read_stencil_span(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1061 GLint n
, GLint x
, GLint y
, GLstencil stencil
[])
1063 if (y
< 0 || y
>= rb
->Height
|| x
+ n
<= 0 || x
>= rb
->Width
) {
1064 /* span is completely outside framebuffer */
1065 return; /* undefined values OK */
1074 if (x
+ n
> rb
->Width
) {
1075 GLint dx
= x
+ n
- rb
->Width
;
1082 rb
->GetRow(ctx
, rb
, n
, x
, y
, stencil
);
1088 * Write a span of stencil values to the stencil buffer.
1089 * Used for glDraw/CopyPixels
1090 * Input: n - how many pixels
1091 * x, y - location of first pixel
1092 * stencil - the array of stencil values
1095 _swrast_write_stencil_span(GLcontext
*ctx
, GLint n
, GLint x
, GLint y
,
1096 const GLstencil stencil
[] )
1098 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1099 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
1101 if (y
< 0 || y
>= rb
->Height
|| x
+ n
<= 0 || x
>= rb
->Width
) {
1102 /* span is completely outside framebuffer */
1103 return; /* undefined values OK */
1111 if (x
+ n
> rb
->Width
) {
1112 GLint dx
= x
+ n
- rb
->Width
;
1119 rb
->PutRow(ctx
, rb
, n
, x
, y
, stencil
, NULL
);
1125 * Clear the stencil buffer.
1128 _swrast_clear_stencil_buffer( GLcontext
*ctx
, struct gl_renderbuffer
*rb
)
1130 const GLubyte stencilBits
= rb
->ComponentSizes
[0];
1131 const GLuint mask
= ctx
->Stencil
.WriteMask
[0];
1132 const GLuint invMask
= ~mask
;
1133 const GLuint clearVal
= (ctx
->Stencil
.Clear
& mask
);
1134 const GLuint stencilMax
= (1 << stencilBits
) - 1;
1135 GLint x
, y
, width
, height
;
1137 if (!rb
|| mask
== 0)
1140 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
||
1141 rb
->DataType
== GL_UNSIGNED_SHORT
);
1143 ASSERT(rb
->_BaseFormat
== GL_STENCIL_INDEX
);
1145 /* compute region to clear */
1146 x
= ctx
->DrawBuffer
->_Xmin
;
1147 y
= ctx
->DrawBuffer
->_Ymin
;
1148 width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
1149 height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
1151 if (rb
->GetPointer(ctx
, rb
, 0, 0)) {
1152 /* Direct buffer access */
1153 if ((mask
& stencilMax
) != stencilMax
) {
1154 /* need to mask the clear */
1155 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1157 for (i
= 0; i
< height
; i
++) {
1158 GLubyte
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1159 for (j
= 0; j
< width
; j
++) {
1160 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1166 for (i
= 0; i
< height
; i
++) {
1167 GLushort
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1168 for (j
= 0; j
< width
; j
++) {
1169 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1175 /* no bit masking */
1176 if (width
== rb
->Width
&& rb
->DataType
== GL_UNSIGNED_BYTE
) {
1177 /* optimized case */
1178 /* XXX bottom-to-op raster assumed! */
1179 GLubyte
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
);
1180 GLuint len
= width
* height
* sizeof(GLubyte
);
1181 _mesa_memset(stencil
, clearVal
, len
);
1186 for (i
= 0; i
< height
; i
++) {
1187 GLvoid
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1188 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1189 _mesa_memset(stencil
, clearVal
, width
);
1192 _mesa_memset16(stencil
, clearVal
, width
);
1199 /* no direct access */
1200 if ((mask
& stencilMax
) != stencilMax
) {
1201 /* need to mask the clear */
1202 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1204 for (i
= 0; i
< height
; i
++) {
1205 GLubyte stencil
[MAX_WIDTH
];
1206 rb
->GetRow(ctx
, rb
, width
, x
, y
+ i
, stencil
);
1207 for (j
= 0; j
< width
; j
++) {
1208 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1210 rb
->PutRow(ctx
, rb
, width
, x
, y
+ i
, stencil
, NULL
);
1215 for (i
= 0; i
< height
; i
++) {
1216 GLushort stencil
[MAX_WIDTH
];
1217 rb
->GetRow(ctx
, rb
, width
, x
, y
+ i
, stencil
);
1218 for (j
= 0; j
< width
; j
++) {
1219 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1221 rb
->PutRow(ctx
, rb
, width
, x
, y
+ i
, stencil
, NULL
);
1226 /* no bit masking */
1227 const GLubyte clear8
= (GLubyte
) clearVal
;
1228 const GLushort clear16
= (GLushort
) clearVal
;
1231 if (rb
->DataType
== GL_UNSIGNED_BYTE
) {
1237 for (i
= 0; i
< height
; i
++) {
1238 rb
->PutMonoRow(ctx
, rb
, width
, x
, y
+ i
, clear
, NULL
);