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"
40 IF stencil test fails THEN
41 Apply fail-op to stencil value
42 Don't write the pixel (RGBA,Z)
44 IF doing depth test && depth test fails THEN
45 Apply zfail-op to stencil value
46 Write RGBA and Z to appropriate buffers
48 Apply zpass-op to stencil value
55 * Apply the given stencil operator to the array of stencil values.
56 * Don't touch stencil[i] if mask[i] is zero.
57 * Input: n - size of stencil array
58 * oper - the stencil buffer operator
59 * face - 0 or 1 for front or back face operation
60 * stencil - array of stencil values
61 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
62 * Output: stencil - modified values
65 apply_stencil_op( const GLcontext
*ctx
, GLenum oper
, GLuint face
,
66 GLuint n
, GLstencil stencil
[], const GLubyte mask
[] )
68 const GLstencil ref
= ctx
->Stencil
.Ref
[face
];
69 const GLstencil wrtmask
= ctx
->Stencil
.WriteMask
[face
];
70 const GLstencil invmask
= (GLstencil
) (~wrtmask
);
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
< STENCIL_MAX
) {
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
< STENCIL_MAX
) {
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
);
397 * Apply stencil and depth testing to the span of pixels.
398 * Both software and hardware stencil buffers are acceptable.
399 * Input: n - number of pixels in the span
400 * x, y - location of leftmost pixel in span
401 * z - array [n] of z values
402 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
403 * Output: mask - array [n] of flags (1=stencil and depth test passed)
404 * Return: GL_FALSE - all fragments failed the testing
405 * GL_TRUE - one or more fragments passed the testing
409 stencil_and_ztest_span(GLcontext
*ctx
, struct sw_span
*span
, GLuint face
)
411 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
412 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
413 GLstencil stencilRow
[MAX_WIDTH
];
415 const GLuint n
= span
->end
;
416 const GLint x
= span
->x
;
417 const GLint y
= span
->y
;
418 GLubyte
*mask
= span
->array
->mask
;
420 ASSERT((span
->arrayMask
& SPAN_XY
) == 0);
421 ASSERT(ctx
->Stencil
.Enabled
);
422 ASSERT(n
<= MAX_WIDTH
);
424 if (ctx
->Depth
.Test
) {
425 ASSERT(span
->arrayMask
& SPAN_Z
);
429 stencil
= rb
->GetPointer(ctx
, rb
, x
, y
);
431 rb
->GetRow(ctx
, rb
, n
, x
, y
, stencilRow
);
432 stencil
= stencilRow
;
436 * Apply the stencil test to the fragments.
437 * failMask[i] is 1 if the stencil test failed.
439 if (do_stencil_test( ctx
, face
, n
, stencil
, mask
) == GL_FALSE
) {
440 /* all fragments failed the stencil test, we're done. */
441 span
->writeAll
= GL_FALSE
;
446 * Some fragments passed the stencil test, apply depth test to them
447 * and apply Zpass and Zfail stencil ops.
449 if (ctx
->Depth
.Test
== GL_FALSE
) {
451 * No depth buffer, just apply zpass stencil function to active pixels.
453 apply_stencil_op( ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
, n
, stencil
, mask
);
457 * Perform depth buffering, then apply zpass or zfail stencil function.
459 GLubyte passmask
[MAX_WIDTH
], failmask
[MAX_WIDTH
], oldmask
[MAX_WIDTH
];
462 /* save the current mask bits */
463 MEMCPY(oldmask
, mask
, n
* sizeof(GLubyte
));
465 /* apply the depth test */
466 _swrast_depth_test_span(ctx
, span
);
468 /* Set the stencil pass/fail flags according to result of depth testing.
469 * if oldmask[i] == 0 then
470 * Don't touch the stencil value
471 * else if oldmask[i] and newmask[i] then
474 * assert(oldmask[i] && !newmask[i])
479 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
480 passmask
[i
] = oldmask
[i
] & mask
[i
];
481 failmask
[i
] = oldmask
[i
] & (mask
[i
] ^ 1);
484 /* apply the pass and fail operations */
485 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
486 apply_stencil_op( ctx
, ctx
->Stencil
.ZFailFunc
[face
], face
,
487 n
, stencil
, failmask
);
489 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
490 apply_stencil_op( ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
491 n
, stencil
, passmask
);
496 * Write updated stencil values back into hardware stencil buffer.
498 if (!rb
->GetPointer(ctx
, rb
, 0, 0)) {
499 rb
->PutRow(ctx
, rb
, n
, x
, y
, stencil
, mask
);
502 span
->writeAll
= GL_FALSE
;
504 return GL_TRUE
; /* one or more fragments passed both tests */
510 * Return the address of a stencil buffer value given the window coords:
512 #define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
517 * Apply the given stencil operator for each pixel in the array whose
519 * \note This is for software stencil buffers only.
520 * Input: n - number of pixels in the span
521 * x, y - array of [n] pixels
522 * operator - the stencil buffer operator
523 * mask - array [n] of flag: 1=apply operator, 0=don't apply operator
526 apply_stencil_op_to_pixels( GLcontext
*ctx
,
527 GLuint n
, const GLint x
[], const GLint y
[],
528 GLenum oper
, GLuint face
, const GLubyte mask
[] )
530 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
531 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
532 const GLstencil ref
= ctx
->Stencil
.Ref
[face
];
533 const GLstencil wrtmask
= ctx
->Stencil
.WriteMask
[face
];
534 const GLstencil invmask
= (GLstencil
) (~wrtmask
);
536 GLstencil
*stencilStart
= (GLubyte
*) rb
->Data
;
537 const GLuint stride
= rb
->Width
;
539 ASSERT(rb
->GetPointer(ctx
, rb
, 0, 0));
540 ASSERT(sizeof(GLstencil
) == 1);
550 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
558 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
559 *sptr
= (GLstencil
) (invmask
& *sptr
);
568 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
576 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
577 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& ref
));
586 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
587 if (*sptr
< STENCIL_MAX
) {
588 *sptr
= (GLstencil
) (*sptr
+ 1);
596 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
597 if (*sptr
< STENCIL_MAX
) {
598 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
+1)));
608 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
610 *sptr
= (GLstencil
) (*sptr
- 1);
618 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
620 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
-1)));
626 case GL_INCR_WRAP_EXT
:
630 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
631 *sptr
= (GLstencil
) (*sptr
+ 1);
638 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
639 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
+1)));
644 case GL_DECR_WRAP_EXT
:
648 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
649 *sptr
= (GLstencil
) (*sptr
- 1);
656 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
657 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& (*sptr
-1)));
666 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
667 *sptr
= (GLstencil
) (~*sptr
);
674 GLstencil
*sptr
= STENCIL_ADDRESS( x
[i
], y
[i
] );
675 *sptr
= (GLstencil
) ((invmask
& *sptr
) | (wrtmask
& ~*sptr
));
681 _mesa_problem(ctx
, "Bad stencilop in apply_stencil_op_to_pixels");
688 * Apply stencil test to an array of pixels before depth buffering.
690 * \note Used for software stencil buffer only.
691 * Input: n - number of pixels in the span
692 * x, y - array of [n] pixels to stencil
693 * mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
694 * Output: mask - pixels which fail the stencil test will have their
695 * mask flag set to 0.
696 * \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
699 stencil_test_pixels( GLcontext
*ctx
, GLuint face
, GLuint n
,
700 const GLint x
[], const GLint y
[], GLubyte mask
[] )
702 const struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
703 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
704 GLubyte fail
[MAX_WIDTH
];
707 GLboolean allfail
= GL_FALSE
;
708 const GLuint valueMask
= ctx
->Stencil
.ValueMask
[face
];
709 const GLstencil
*stencilStart
= (GLstencil
*) rb
->Data
;
710 const GLuint stride
= rb
->Width
;
712 ASSERT(rb
->GetPointer(ctx
, rb
, 0, 0));
713 ASSERT(sizeof(GLstencil
) == 1);
716 * Perform stencil test. The results of this operation are stored
717 * in the fail[] array:
718 * IF fail[i] is non-zero THEN
719 * the stencil fail operator is to be applied
721 * the stencil fail operator is not to be applied
725 switch (ctx
->Stencil
.Function
[face
]) {
740 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
743 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
744 s
= (GLstencil
) (*sptr
& valueMask
);
760 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
763 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
764 s
= (GLstencil
) (*sptr
& valueMask
);
780 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
783 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
784 s
= (GLstencil
) (*sptr
& valueMask
);
800 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
803 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
804 s
= (GLstencil
) (*sptr
& valueMask
);
820 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
823 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
824 s
= (GLstencil
) (*sptr
& valueMask
);
840 r
= (GLstencil
) (ctx
->Stencil
.Ref
[face
] & valueMask
);
843 const GLstencil
*sptr
= STENCIL_ADDRESS(x
[i
],y
[i
]);
844 s
= (GLstencil
) (*sptr
& valueMask
);
866 _mesa_problem(ctx
, "Bad stencil func in gl_stencil_pixels");
870 if (ctx
->Stencil
.FailFunc
[face
] != GL_KEEP
) {
871 apply_stencil_op_to_pixels( ctx
, n
, x
, y
, ctx
->Stencil
.FailFunc
[face
],
882 * Apply stencil and depth testing to an array of pixels.
883 * This is used both for software and hardware stencil buffers.
885 * The comments in this function are a bit sparse but the code is
886 * almost identical to stencil_and_ztest_span(), which is well
889 * Input: n - number of pixels in the array
890 * x, y - array of [n] pixel positions
891 * z - array [n] of z values
892 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
893 * Output: mask - array [n] of flags (1=stencil and depth test passed)
894 * Return: GL_FALSE - all fragments failed the testing
895 * GL_TRUE - one or more fragments passed the testing
898 stencil_and_ztest_pixels( GLcontext
*ctx
, struct sw_span
*span
, GLuint face
)
900 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
901 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
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
;
907 ASSERT(span
->arrayMask
& SPAN_XY
);
908 ASSERT(ctx
->Stencil
.Enabled
);
909 ASSERT(n
<= MAX_WIDTH
);
911 if (!rb
->GetPointer(ctx
, rb
, 0, 0)) {
912 /* No direct access */
913 GLstencil stencil
[MAX_WIDTH
];
914 GLubyte origMask
[MAX_WIDTH
];
916 rb
->GetValues(ctx
, rb
, n
, x
, y
, stencil
);
918 MEMCPY(origMask
, mask
, n
* sizeof(GLubyte
));
920 (void) do_stencil_test(ctx
, face
, n
, stencil
, mask
);
922 if (ctx
->Depth
.Test
== GL_FALSE
) {
923 apply_stencil_op(ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
927 _swrast_depth_test_span(ctx
, span
);
929 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
930 GLubyte failmask
[MAX_WIDTH
];
932 for (i
= 0; i
< n
; i
++) {
933 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
934 failmask
[i
] = origMask
[i
] & (mask
[i
] ^ 1);
936 apply_stencil_op(ctx
, ctx
->Stencil
.ZFailFunc
[face
], face
,
937 n
, stencil
, failmask
);
939 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
940 GLubyte passmask
[MAX_WIDTH
];
942 for (i
= 0; i
< n
; i
++) {
943 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
944 passmask
[i
] = origMask
[i
] & mask
[i
];
946 apply_stencil_op(ctx
, ctx
->Stencil
.ZPassFunc
[face
], face
,
947 n
, stencil
, passmask
);
951 /* Write updated stencil values into hardware stencil buffer */
952 rb
->PutValues(ctx
, rb
, n
, x
, y
, stencil
, origMask
);
957 /* Direct access to stencil buffer */
959 if (stencil_test_pixels(ctx
, face
, n
, x
, y
, mask
) == GL_FALSE
) {
960 /* all fragments failed the stencil test, we're done. */
964 if (ctx
->Depth
.Test
==GL_FALSE
) {
965 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
966 ctx
->Stencil
.ZPassFunc
[face
], face
, mask
);
969 GLubyte passmask
[MAX_WIDTH
], failmask
[MAX_WIDTH
], oldmask
[MAX_WIDTH
];
972 MEMCPY(oldmask
, mask
, n
* sizeof(GLubyte
));
974 _swrast_depth_test_span(ctx
, span
);
977 ASSERT(mask
[i
] == 0 || mask
[i
] == 1);
978 passmask
[i
] = oldmask
[i
] & mask
[i
];
979 failmask
[i
] = oldmask
[i
] & (mask
[i
] ^ 1);
982 if (ctx
->Stencil
.ZFailFunc
[face
] != GL_KEEP
) {
983 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
984 ctx
->Stencil
.ZFailFunc
[face
],
987 if (ctx
->Stencil
.ZPassFunc
[face
] != GL_KEEP
) {
988 apply_stencil_op_to_pixels(ctx
, n
, x
, y
,
989 ctx
->Stencil
.ZPassFunc
[face
],
994 return GL_TRUE
; /* one or more fragments passed both tests */
1000 * /return GL_TRUE = one or more fragments passed,
1001 * GL_FALSE = all fragments failed.
1004 _swrast_stencil_and_ztest_span(GLcontext
*ctx
, struct sw_span
*span
)
1006 /* span->facing can only be non-zero if using two-sided stencil */
1007 ASSERT(ctx
->Stencil
.TestTwoSide
|| span
->facing
== 0);
1008 if (span
->arrayMask
& SPAN_XY
)
1009 return stencil_and_ztest_pixels(ctx
, span
, span
->facing
);
1011 return stencil_and_ztest_span(ctx
, span
, span
->facing
);
1017 clip_span(GLuint bufferWidth
, GLuint bufferHeight
,
1018 GLint x
, GLint y
, GLuint
*count
)
1021 GLuint skipPixels
= 0;
1023 if (y
< 0 || y
>= bufferHeight
|| x
+ n
<= 0 || x
>= bufferWidth
) {
1024 /* totally out of bounds */
1035 if (x
+ n
> bufferWidth
) {
1036 GLint dx
= x
+ n
- bufferWidth
;
1049 * Return a span of stencil values from the stencil buffer.
1050 * Used for glRead/CopyPixels
1051 * Input: n - how many pixels
1052 * x,y - location of first pixel
1053 * Output: stencil - the array of stencil values
1056 _swrast_read_stencil_span(GLcontext
*ctx
, struct gl_renderbuffer
*rb
,
1057 GLint n
, GLint x
, GLint y
, GLstencil stencil
[])
1059 if (y
< 0 || y
>= rb
->Height
|| x
+ n
<= 0 || x
>= rb
->Width
) {
1060 /* span is completely outside framebuffer */
1061 return; /* undefined values OK */
1070 if (x
+ n
> rb
->Width
) {
1071 GLint dx
= x
+ n
- rb
->Width
;
1078 rb
->GetRow(ctx
, rb
, n
, x
, y
, stencil
);
1084 * Write a span of stencil values to the stencil buffer.
1085 * Used for glDraw/CopyPixels
1086 * Input: n - how many pixels
1087 * x, y - location of first pixel
1088 * stencil - the array of stencil values
1091 _swrast_write_stencil_span(GLcontext
*ctx
, GLint n
, GLint x
, GLint y
,
1092 const GLstencil stencil
[] )
1094 struct gl_framebuffer
*fb
= ctx
->DrawBuffer
;
1095 struct gl_renderbuffer
*rb
= fb
->Attachment
[BUFFER_STENCIL
].Renderbuffer
;
1097 if (y
< 0 || y
>= rb
->Height
|| x
+ n
<= 0 || x
>= rb
->Width
) {
1098 /* span is completely outside framebuffer */
1099 return; /* undefined values OK */
1107 if (x
+ n
> rb
->Width
) {
1108 GLint dx
= x
+ n
- rb
->Width
;
1115 rb
->PutRow(ctx
, rb
, n
, x
, y
, stencil
, NULL
);
1121 * Clear the stencil buffer.
1124 _swrast_clear_stencil_buffer( GLcontext
*ctx
, struct gl_renderbuffer
*rb
)
1126 const GLstencil mask
= ctx
->Stencil
.WriteMask
[0];
1127 const GLstencil invMask
= ~mask
;
1128 const GLstencil clearVal
= (ctx
->Stencil
.Clear
& mask
);
1129 GLint x
, y
, width
, height
;
1131 if (!rb
|| mask
== 0)
1134 ASSERT(rb
->DataType
== GL_UNSIGNED_BYTE
);
1135 ASSERT(rb
->_BaseFormat
== GL_STENCIL_INDEX
);
1137 /* compute region to clear */
1138 x
= ctx
->DrawBuffer
->_Xmin
;
1139 y
= ctx
->DrawBuffer
->_Ymin
;
1140 width
= ctx
->DrawBuffer
->_Xmax
- ctx
->DrawBuffer
->_Xmin
;
1141 height
= ctx
->DrawBuffer
->_Ymax
- ctx
->DrawBuffer
->_Ymin
;
1143 if (rb
->GetPointer(ctx
, rb
, 0, 0)) {
1144 /* Direct buffer access */
1145 if (ctx
->Stencil
.WriteMask
[0] != STENCIL_MAX
) {
1146 /* need to mask the clear */
1148 for (i
= 0; i
< height
; i
++) {
1149 GLubyte
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1150 for (j
= 0; j
< width
; j
++) {
1151 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1156 /* no bit masking */
1157 if (width
== rb
->Width
&&
1158 rb
->InternalFormat
== GL_STENCIL_INDEX8_EXT
) {
1159 /* optimized case */
1160 GLubyte
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
);
1161 GLuint len
= width
* height
* sizeof(GLubyte
);
1162 _mesa_memset(stencil
, clearVal
, len
);
1167 for (i
= 0; i
< height
; i
++) {
1168 GLubyte
*stencil
= rb
->GetPointer(ctx
, rb
, x
, y
+ i
);
1169 for (j
= 0; j
< width
; j
++) {
1170 stencil
[j
] = clearVal
;
1177 /* no direct access */
1178 if (ctx
->Stencil
.WriteMask
[0] != STENCIL_MAX
) {
1179 /* need to mask the clear */
1181 for (i
= 0; i
< height
; i
++) {
1182 GLubyte stencil
[MAX_WIDTH
];
1183 rb
->GetRow(ctx
, rb
, width
, x
, y
+ i
, stencil
);
1184 for (j
= 0; j
< width
; j
++) {
1185 stencil
[j
] = (stencil
[j
] & invMask
) | clearVal
;
1187 rb
->PutRow(ctx
, rb
, width
, x
, y
+ i
, stencil
, NULL
);
1191 /* no bit masking */
1192 const GLubyte clear8
= clearVal
;
1194 for (i
= 0; i
< height
; i
++) {
1195 rb
->PutMonoRow(ctx
, rb
, width
, x
, y
+ i
, &clear8
, NULL
);