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 struct gl_context *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( struct gl_context *ctx, GLuint face, GLuint n, GLstencil stencil[],
231 GLubyte fail[MAX_WIDTH];
232 GLboolean allfail = GL_FALSE;
234 const GLuint valueMask = ctx->Stencil.ValueMask[face];
235 const GLstencil r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
238 ASSERT(n <= MAX_WIDTH);
241 * Perform stencil test. The results of this operation are stored
242 * in the fail[] array:
243 * IF fail[i] is non-zero THEN
244 * the stencil fail operator is to be applied
246 * the stencil fail operator is not to be applied
249 switch (ctx->Stencil.Function[face]) {
251 /* never pass; always fail */
266 s = (GLstencil) (stencil[i] & valueMask);
284 s = (GLstencil) (stencil[i] & valueMask);
302 s = (GLstencil) (stencil[i] & valueMask);
320 s = (GLstencil) (stencil[i] & valueMask);
338 s = (GLstencil) (stencil[i] & valueMask);
356 s = (GLstencil) (stencil[i] & valueMask);
378 _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
382 if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
383 apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );
391 * Compute the zpass/zfail masks by comparing the pre- and post-depth test
395 compute_pass_fail_masks(GLuint n, const GLubyte origMask[],
396 const GLubyte newMask[],
397 GLubyte passMask[], GLubyte failMask[])
400 for (i = 0; i < n; i++) {
401 ASSERT(newMask[i] == 0 || newMask[i] == 1);
402 passMask[i] = origMask[i] & newMask[i];
403 failMask[i] = origMask[i] & (newMask[i] ^ 1);
409 * Apply stencil and depth testing to the span of pixels.
410 * Both software and hardware stencil buffers are acceptable.
411 * Input: n - number of pixels in the span
412 * x, y - location of leftmost pixel in span
413 * z - array [n] of z values
414 * mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
415 * Output: mask - array [n] of flags (1=stencil and depth test passed)
416 * Return: GL_FALSE - all fragments failed the testing
417 * GL_TRUE - one or more fragments passed the testing
421 stencil_and_ztest_span(struct gl_context *ctx, SWspan *span, GLuint face)
423 struct gl_framebuffer *fb = ctx->DrawBuffer;
424 struct gl_renderbuffer *rb = fb->_StencilBuffer;
425 GLstencil stencilRow[MAX_WIDTH];
427 const GLuint n = span->end;
428 const GLint x = span->x;
429 const GLint y = span->y;
430 GLubyte *mask = span->array->mask;
432 ASSERT((span->arrayMask & SPAN_XY) == 0);
433 ASSERT(ctx->Stencil.Enabled);
434 ASSERT(n <= MAX_WIDTH);
436 if (ctx->Depth.Test) {
437 ASSERT(span->arrayMask & SPAN_Z);
441 stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);
443 rb->GetRow(ctx, rb, n, x, y, stencilRow);
444 stencil = stencilRow;
448 * Apply the stencil test to the fragments.
449 * failMask[i] is 1 if the stencil test failed.
451 if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {
452 /* all fragments failed the stencil test, we're done. */
453 span->writeAll = GL_FALSE;
454 if (!rb->GetPointer(ctx, rb, 0, 0)) {
455 /* put updated stencil values into buffer */
456 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
462 * Some fragments passed the stencil test, apply depth test to them
463 * and apply Zpass and Zfail stencil ops.
465 if (ctx->Depth.Test == GL_FALSE ||
466 ctx->DrawBuffer->_DepthBuffer == NULL) {
468 * No depth buffer, just apply zpass stencil function to active pixels.
470 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
474 * Perform depth buffering, then apply zpass or zfail stencil function.
476 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
478 /* save the current mask bits */
479 memcpy(origMask, mask, n * sizeof(GLubyte));
481 /* apply the depth test */
482 _swrast_depth_test_span(ctx, span);
484 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
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, NULL);
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( struct gl_context *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->_StencilBuffer;
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( struct gl_context *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->_StencilBuffer;
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( struct gl_context *ctx, SWspan *span, GLuint face )
903 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];
904 struct gl_framebuffer *fb = ctx->DrawBuffer;
905 struct gl_renderbuffer *rb = fb->_StencilBuffer;
906 const GLuint n = span->end;
907 const GLint *x = span->array->x;
908 const GLint *y = span->array->y;
909 GLubyte *mask = span->array->mask;
911 ASSERT(span->arrayMask & SPAN_XY);
912 ASSERT(ctx->Stencil.Enabled);
913 ASSERT(n <= MAX_WIDTH);
915 if (!rb->GetPointer(ctx, rb, 0, 0)) {
916 /* No direct access */
917 GLstencil stencil[MAX_WIDTH];
919 ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
920 _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
922 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 GLubyte tmpMask[MAX_WIDTH];
932 memcpy(tmpMask, mask, n * sizeof(GLubyte));
934 _swrast_depth_test_span(ctx, span);
936 compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);
938 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
939 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
940 n, stencil, failMask);
942 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
943 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
944 n, stencil, passMask);
948 /* Write updated stencil values into hardware stencil buffer */
949 rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
954 /* Direct access to stencil buffer */
956 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
957 /* all fragments failed the stencil test, we're done. */
961 if (ctx->Depth.Test==GL_FALSE) {
962 apply_stencil_op_to_pixels(ctx, n, x, y,
963 ctx->Stencil.ZPassFunc[face], face, mask);
966 memcpy(origMask, mask, n * sizeof(GLubyte));
968 _swrast_depth_test_span(ctx, span);
970 compute_pass_fail_masks(n, origMask, mask, passMask, failMask);
972 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
973 apply_stencil_op_to_pixels(ctx, n, x, y,
974 ctx->Stencil.ZFailFunc[face],
977 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
978 apply_stencil_op_to_pixels(ctx, n, x, y,
979 ctx->Stencil.ZPassFunc[face],
984 return GL_TRUE; /* one or more fragments passed both tests */
990 * /return GL_TRUE = one or more fragments passed,
991 * GL_FALSE = all fragments failed.
994 _swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span)
996 const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace;
998 if (span->arrayMask & SPAN_XY)
999 return stencil_and_ztest_pixels(ctx, span, face);
1001 return stencil_and_ztest_span(ctx, span, face);
1007 clip_span(GLuint bufferWidth, GLuint bufferHeight,
1008 GLint x, GLint y, GLuint *count)
1011 GLuint skipPixels = 0;
1013 if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {
1014 /* totally out of bounds */
1025 if (x + n > bufferWidth) {
1026 GLint dx = x + n - bufferWidth;
1039 * Return a span of stencil values from the stencil buffer.
1040 * Used for glRead/CopyPixels
1041 * Input: n - how many pixels
1042 * x,y - location of first pixel
1043 * Output: stencil - the array of stencil values
1046 _swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb,
1047 GLint n, GLint x, GLint y, GLstencil stencil[])
1049 if (y < 0 || y >= (GLint) rb->Height ||
1050 x + n <= 0 || x >= (GLint) rb->Width) {
1051 /* span is completely outside framebuffer */
1052 return; /* undefined values OK */
1061 if (x + n > (GLint) rb->Width) {
1062 GLint dx = x + n - rb->Width;
1069 rb->GetRow(ctx, rb, n, x, y, stencil);
1075 * Write a span of stencil values to the stencil buffer. This function
1076 * applies the stencil write mask when needed.
1077 * Used for glDraw/CopyPixels
1078 * Input: n - how many pixels
1079 * x, y - location of first pixel
1080 * stencil - the array of stencil values
1083 _swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y,
1084 const GLstencil stencil[] )
1086 struct gl_framebuffer *fb = ctx->DrawBuffer;
1087 struct gl_renderbuffer *rb = fb->_StencilBuffer;
1088 const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1089 const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1091 if (y < 0 || y >= (GLint) rb->Height ||
1092 x + n <= 0 || x >= (GLint) rb->Width) {
1093 /* span is completely outside framebuffer */
1094 return; /* undefined values OK */
1102 if (x + n > (GLint) rb->Width) {
1103 GLint dx = x + n - rb->Width;
1110 if ((stencilMask & stencilMax) != stencilMax) {
1111 /* need to apply writemask */
1112 GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1114 rb->GetRow(ctx, rb, n, x, y, destVals);
1115 for (i = 0; i < n; i++) {
1117 = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1119 rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1122 rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1129 * Clear the stencil buffer.
1132 _swrast_clear_stencil_buffer( struct gl_context *ctx, struct gl_renderbuffer *rb )
1134 const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1135 const GLuint mask = ctx->Stencil.WriteMask[0];
1136 const GLuint invMask = ~mask;
1137 const GLuint clearVal = (ctx->Stencil.Clear & mask);
1138 const GLuint stencilMax = (1 << stencilBits) - 1;
1139 GLint x, y, width, height;
1141 if (!rb || mask == 0)
1144 ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1145 rb->DataType == GL_UNSIGNED_SHORT);
1147 ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1149 /* compute region to clear */
1150 x = ctx->DrawBuffer->_Xmin;
1151 y = ctx->DrawBuffer->_Ymin;
1152 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1153 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1155 if (rb->GetPointer(ctx, rb, 0, 0)) {
1156 /* Direct buffer access */
1157 if ((mask & stencilMax) != stencilMax) {
1158 /* need to mask the clear */
1159 if (rb->DataType == GL_UNSIGNED_BYTE) {
1161 for (i = 0; i < height; i++) {
1162 GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
1163 for (j = 0; j < width; j++) {
1164 stencil[j] = (stencil[j] & invMask) | clearVal;
1170 for (i = 0; i < height; i++) {
1171 GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
1172 for (j = 0; j < width; j++) {
1173 stencil[j] = (stencil[j] & invMask) | clearVal;
1179 /* no bit masking */
1180 if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1181 /* optimized case */
1182 /* Note: bottom-to-top raster assumed! */
1183 GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
1184 GLuint len = width * height * sizeof(GLubyte);
1185 memset(stencil, clearVal, len);
1190 for (i = 0; i < height; i++) {
1191 GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1192 if (rb->DataType == GL_UNSIGNED_BYTE) {
1193 memset(stencil, clearVal, width);
1196 _mesa_memset16((short unsigned int*) stencil, clearVal, width);
1203 /* no direct access */
1204 if ((mask & stencilMax) != stencilMax) {
1205 /* need to mask the clear */
1206 if (rb->DataType == GL_UNSIGNED_BYTE) {
1208 for (i = 0; i < height; i++) {
1209 GLubyte stencil[MAX_WIDTH];
1210 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1211 for (j = 0; j < width; j++) {
1212 stencil[j] = (stencil[j] & invMask) | clearVal;
1214 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1219 for (i = 0; i < height; i++) {
1220 GLushort stencil[MAX_WIDTH];
1221 rb->GetRow(ctx, rb, width, x, y + i, stencil);
1222 for (j = 0; j < width; j++) {
1223 stencil[j] = (stencil[j] & invMask) | clearVal;
1225 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1230 /* no bit masking */
1231 const GLubyte clear8 = (GLubyte) clearVal;
1232 const GLushort clear16 = (GLushort) clearVal;
1235 if (rb->DataType == GL_UNSIGNED_BYTE) {
1241 for (i = 0; i < height; i++) {
1242 rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);