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.
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 );
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, SWspan *span, GLuint face)
411
struct gl_framebuffer *fb = ctx->DrawBuffer;
412
struct gl_renderbuffer *rb = fb->_StencilBuffer;
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 = (GLstencil *) 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;
442
if (!rb->GetPointer(ctx, rb, 0, 0)) {
443
/* put updated stencil values into buffer */
444
rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
450
* Some fragments passed the stencil test, apply depth test to them
451
* and apply Zpass and Zfail stencil ops.
453
if (ctx->Depth.Test == GL_FALSE) {
455
* No depth buffer, just apply zpass stencil function to active pixels.
457
apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );
461
* Perform depth buffering, then apply zpass or zfail stencil function.
463
GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
466
/* save the current mask bits */
467
_mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
469
/* apply the depth test */
470
_swrast_depth_test_span(ctx, span);
472
/* Set the stencil pass/fail flags according to result of depth testing.
473
* if oldmask[i] == 0 then
474
* Don't touch the stencil value
475
* else if oldmask[i] and newmask[i] then
478
* assert(oldmask[i] && !newmask[i])
483
ASSERT(mask[i] == 0 || mask[i] == 1);
484
passmask[i] = oldmask[i] & mask[i];
485
failmask[i] = oldmask[i] & (mask[i] ^ 1);
488
/* apply the pass and fail operations */
489
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
490
apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,
491
n, stencil, failmask );
493
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
494
apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,
495
n, stencil, passmask );
500
* Write updated stencil values back into hardware stencil buffer.
502
if (!rb->GetPointer(ctx, rb, 0, 0)) {
503
rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
506
span->writeAll = GL_FALSE;
508
return GL_TRUE; /* one or more fragments passed both tests */
514
* Return the address of a stencil buffer value given the window coords:
516
#define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X))
521
* Apply the given stencil operator for each pixel in the array whose
523
* \note This is for software stencil buffers only.
524
* Input: n - number of pixels in the span
525
* x, y - array of [n] pixels
526
* operator - the stencil buffer operator
527
* mask - array [n] of flag: 1=apply operator, 0=don't apply operator
530
apply_stencil_op_to_pixels( GLcontext *ctx,
531
GLuint n, const GLint x[], const GLint y[],
532
GLenum oper, GLuint face, const GLubyte mask[] )
534
struct gl_framebuffer *fb = ctx->DrawBuffer;
535
struct gl_renderbuffer *rb = fb->_StencilBuffer;
536
const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;
537
const GLstencil ref = ctx->Stencil.Ref[face];
538
const GLstencil wrtmask = ctx->Stencil.WriteMask[face];
539
const GLstencil invmask = (GLstencil) (~wrtmask);
541
GLstencil *stencilStart = (GLubyte *) rb->Data;
542
const GLuint stride = rb->Width;
544
ASSERT(rb->GetPointer(ctx, rb, 0, 0));
545
ASSERT(sizeof(GLstencil) == 1);
555
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
563
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
564
*sptr = (GLstencil) (invmask & *sptr);
573
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
581
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
582
*sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
591
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
592
if (*sptr < stencilMax) {
593
*sptr = (GLstencil) (*sptr + 1);
601
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
602
if (*sptr < stencilMax) {
603
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
613
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
615
*sptr = (GLstencil) (*sptr - 1);
623
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
625
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
631
case GL_INCR_WRAP_EXT:
635
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
636
*sptr = (GLstencil) (*sptr + 1);
643
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
644
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
649
case GL_DECR_WRAP_EXT:
653
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
654
*sptr = (GLstencil) (*sptr - 1);
661
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
662
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
671
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
672
*sptr = (GLstencil) (~*sptr);
679
GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
680
*sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
686
_mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
693
* Apply stencil test to an array of pixels before depth buffering.
695
* \note Used for software stencil buffer only.
696
* Input: n - number of pixels in the span
697
* x, y - array of [n] pixels to stencil
698
* mask - array [n] of flag: 0=skip the pixel, 1=stencil the pixel
699
* Output: mask - pixels which fail the stencil test will have their
700
* mask flag set to 0.
701
* \return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
704
stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,
705
const GLint x[], const GLint y[], GLubyte mask[] )
707
const struct gl_framebuffer *fb = ctx->DrawBuffer;
708
struct gl_renderbuffer *rb = fb->_StencilBuffer;
709
GLubyte fail[MAX_WIDTH];
712
GLboolean allfail = GL_FALSE;
713
const GLuint valueMask = ctx->Stencil.ValueMask[face];
714
const GLstencil *stencilStart = (GLstencil *) rb->Data;
715
const GLuint stride = rb->Width;
717
ASSERT(rb->GetPointer(ctx, rb, 0, 0));
718
ASSERT(sizeof(GLstencil) == 1);
721
* Perform stencil test. The results of this operation are stored
722
* in the fail[] array:
723
* IF fail[i] is non-zero THEN
724
* the stencil fail operator is to be applied
726
* the stencil fail operator is not to be applied
730
switch (ctx->Stencil.Function[face]) {
745
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
748
const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
749
s = (GLstencil) (*sptr & valueMask);
765
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
768
const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
769
s = (GLstencil) (*sptr & valueMask);
785
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
788
const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
789
s = (GLstencil) (*sptr & valueMask);
805
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
808
const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
809
s = (GLstencil) (*sptr & valueMask);
825
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
828
const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
829
s = (GLstencil) (*sptr & valueMask);
845
r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);
848
const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
849
s = (GLstencil) (*sptr & valueMask);
871
_mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
875
if (ctx->Stencil.FailFunc[face] != GL_KEEP) {
876
apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],
887
* Apply stencil and depth testing to an array of pixels.
888
* This is used both for software and hardware stencil buffers.
890
* The comments in this function are a bit sparse but the code is
891
* almost identical to stencil_and_ztest_span(), which is well
894
* Input: n - number of pixels in the array
895
* x, y - array of [n] pixel positions
896
* z - array [n] of z values
897
* mask - array [n] of flags (1=test this pixel, 0=skip the pixel)
898
* Output: mask - array [n] of flags (1=stencil and depth test passed)
899
* Return: GL_FALSE - all fragments failed the testing
900
* GL_TRUE - one or more fragments passed the testing
903
stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face )
905
struct gl_framebuffer *fb = ctx->DrawBuffer;
906
struct gl_renderbuffer *rb = fb->_StencilBuffer;
907
const GLuint n = span->end;
908
const GLint *x = span->array->x;
909
const GLint *y = span->array->y;
910
GLubyte *mask = span->array->mask;
912
ASSERT(span->arrayMask & SPAN_XY);
913
ASSERT(ctx->Stencil.Enabled);
914
ASSERT(n <= MAX_WIDTH);
916
if (!rb->GetPointer(ctx, rb, 0, 0)) {
917
/* No direct access */
918
GLstencil stencil[MAX_WIDTH];
919
GLubyte origMask[MAX_WIDTH];
921
ASSERT(rb->DataType == GL_UNSIGNED_BYTE);
922
_swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));
924
_mesa_memcpy(origMask, mask, n * sizeof(GLubyte));
926
(void) do_stencil_test(ctx, face, n, stencil, mask);
928
if (ctx->Depth.Test == GL_FALSE) {
929
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
933
_swrast_depth_test_span(ctx, span);
935
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
936
GLubyte failmask[MAX_WIDTH];
938
for (i = 0; i < n; i++) {
939
ASSERT(mask[i] == 0 || mask[i] == 1);
940
failmask[i] = origMask[i] & (mask[i] ^ 1);
942
apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face,
943
n, stencil, failmask);
945
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
946
GLubyte passmask[MAX_WIDTH];
948
for (i = 0; i < n; i++) {
949
ASSERT(mask[i] == 0 || mask[i] == 1);
950
passmask[i] = origMask[i] & mask[i];
952
apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,
953
n, stencil, passmask);
957
/* Write updated stencil values into hardware stencil buffer */
958
rb->PutValues(ctx, rb, n, x, y, stencil, origMask);
963
/* Direct access to stencil buffer */
965
if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {
966
/* all fragments failed the stencil test, we're done. */
970
if (ctx->Depth.Test==GL_FALSE) {
971
apply_stencil_op_to_pixels(ctx, n, x, y,
972
ctx->Stencil.ZPassFunc[face], face, mask);
975
GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH];
978
_mesa_memcpy(oldmask, mask, n * sizeof(GLubyte));
980
_swrast_depth_test_span(ctx, span);
983
ASSERT(mask[i] == 0 || mask[i] == 1);
984
passmask[i] = oldmask[i] & mask[i];
985
failmask[i] = oldmask[i] & (mask[i] ^ 1);
988
if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {
989
apply_stencil_op_to_pixels(ctx, n, x, y,
990
ctx->Stencil.ZFailFunc[face],
993
if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {
994
apply_stencil_op_to_pixels(ctx, n, x, y,
995
ctx->Stencil.ZPassFunc[face],
1000
return GL_TRUE; /* one or more fragments passed both tests */
1006
* /return GL_TRUE = one or more fragments passed,
1007
* GL_FALSE = all fragments failed.
1010
_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span)
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 >= (GLint) rb->Height ||
1064
x + n <= 0 || x >= (GLint) rb->Width) {
1065
/* span is completely outside framebuffer */
1066
return; /* undefined values OK */
1075
if (x + n > (GLint) rb->Width) {
1076
GLint dx = x + n - rb->Width;
1083
rb->GetRow(ctx, rb, n, x, y, stencil);
1089
* Write a span of stencil values to the stencil buffer. This function
1090
* applies the stencil write mask when needed.
1091
* Used for glDraw/CopyPixels
1092
* Input: n - how many pixels
1093
* x, y - location of first pixel
1094
* stencil - the array of stencil values
1097
_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,
1098
const GLstencil stencil[] )
1100
struct gl_framebuffer *fb = ctx->DrawBuffer;
1101
struct gl_renderbuffer *rb = fb->_StencilBuffer;
1102
const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;
1103
const GLuint stencilMask = ctx->Stencil.WriteMask[0];
1105
if (y < 0 || y >= (GLint) rb->Height ||
1106
x + n <= 0 || x >= (GLint) rb->Width) {
1107
/* span is completely outside framebuffer */
1108
return; /* undefined values OK */
1116
if (x + n > (GLint) rb->Width) {
1117
GLint dx = x + n - rb->Width;
1124
if ((stencilMask & stencilMax) != stencilMax) {
1125
/* need to apply writemask */
1126
GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];
1128
rb->GetRow(ctx, rb, n, x, y, destVals);
1129
for (i = 0; i < n; i++) {
1131
= (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);
1133
rb->PutRow(ctx, rb, n, x, y, newVals, NULL);
1136
rb->PutRow(ctx, rb, n, x, y, stencil, NULL);
1143
* Clear the stencil buffer.
1146
_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
1148
const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;
1149
const GLuint mask = ctx->Stencil.WriteMask[0];
1150
const GLuint invMask = ~mask;
1151
const GLuint clearVal = (ctx->Stencil.Clear & mask);
1152
const GLuint stencilMax = (1 << stencilBits) - 1;
1153
GLint x, y, width, height;
1155
if (!rb || mask == 0)
1158
ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||
1159
rb->DataType == GL_UNSIGNED_SHORT);
1161
ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);
1163
/* compute region to clear */
1164
x = ctx->DrawBuffer->_Xmin;
1165
y = ctx->DrawBuffer->_Ymin;
1166
width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
1167
height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
1169
if (rb->GetPointer(ctx, rb, 0, 0)) {
1170
/* Direct buffer access */
1171
if ((mask & stencilMax) != stencilMax) {
1172
/* need to mask the clear */
1173
if (rb->DataType == GL_UNSIGNED_BYTE) {
1175
for (i = 0; i < height; i++) {
1176
GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);
1177
for (j = 0; j < width; j++) {
1178
stencil[j] = (stencil[j] & invMask) | clearVal;
1184
for (i = 0; i < height; i++) {
1185
GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);
1186
for (j = 0; j < width; j++) {
1187
stencil[j] = (stencil[j] & invMask) | clearVal;
1193
/* no bit masking */
1194
if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {
1195
/* optimized case */
1196
/* Note: bottom-to-top raster assumed! */
1197
GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);
1198
GLuint len = width * height * sizeof(GLubyte);
1199
_mesa_memset(stencil, clearVal, len);
1204
for (i = 0; i < height; i++) {
1205
GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);
1206
if (rb->DataType == GL_UNSIGNED_BYTE) {
1207
_mesa_memset(stencil, clearVal, width);
1210
_mesa_memset16((short unsigned int*) stencil, clearVal, width);
1217
/* no direct access */
1218
if ((mask & stencilMax) != stencilMax) {
1219
/* need to mask the clear */
1220
if (rb->DataType == GL_UNSIGNED_BYTE) {
1222
for (i = 0; i < height; i++) {
1223
GLubyte stencil[MAX_WIDTH];
1224
rb->GetRow(ctx, rb, width, x, y + i, stencil);
1225
for (j = 0; j < width; j++) {
1226
stencil[j] = (stencil[j] & invMask) | clearVal;
1228
rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1233
for (i = 0; i < height; i++) {
1234
GLushort stencil[MAX_WIDTH];
1235
rb->GetRow(ctx, rb, width, x, y + i, stencil);
1236
for (j = 0; j < width; j++) {
1237
stencil[j] = (stencil[j] & invMask) | clearVal;
1239
rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);
1244
/* no bit masking */
1245
const GLubyte clear8 = (GLubyte) clearVal;
1246
const GLushort clear16 = (GLushort) clearVal;
1249
if (rb->DataType == GL_UNSIGNED_BYTE) {
1255
for (i = 0; i < height; i++) {
1256
rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);