s_stencil.c revision 7ec681f3
1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the "Software"), 8 * to deal in the Software without restriction, including without limitation 9 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 * and/or sell copies of the Software, and to permit persons to whom the 11 * Software is furnished to do so, subject to the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be included 14 * in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 17 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 * OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25 26#include "main/glheader.h" 27#include "main/context.h" 28 29#include "main/format_pack.h" 30#include "main/format_unpack.h" 31#include "main/stencil.h" 32 33#include "s_context.h" 34#include "s_depth.h" 35#include "s_stencil.h" 36#include "s_span.h" 37 38 39 40/* Stencil Logic: 41 42IF stencil test fails THEN 43 Apply fail-op to stencil value 44 Don't write the pixel (RGBA,Z) 45ELSE 46 IF doing depth test && depth test fails THEN 47 Apply zfail-op to stencil value 48 Write RGBA and Z to appropriate buffers 49 ELSE 50 Apply zpass-op to stencil value 51ENDIF 52 53*/ 54 55 56 57/** 58 * Compute/return the offset of the stencil value in a pixel. 59 * For example, if the format is Z24+S8, the position of the stencil bits 60 * within the 4-byte pixel will be either 0 or 3. 61 */ 62static GLint 63get_stencil_offset(mesa_format format) 64{ 65 const GLubyte one = 1; 66 GLubyte pixel[MAX_PIXEL_BYTES]; 67 GLint bpp = _mesa_get_format_bytes(format); 68 GLint i; 69 70 assert(_mesa_get_format_bits(format, GL_STENCIL_BITS) == 8); 71 memset(pixel, 0, sizeof(pixel)); 72 _mesa_pack_ubyte_stencil_row(format, 1, &one, pixel); 73 74 for (i = 0; i < bpp; i++) { 75 if (pixel[i]) 76 return i; 77 } 78 79 _mesa_problem(NULL, "get_stencil_offset() failed\n"); 80 return 0; 81} 82 83 84/** Clamp the stencil value to [0, 255] */ 85static inline GLubyte 86clamp(GLint val) 87{ 88 if (val < 0) 89 return 0; 90 else if (val > 255) 91 return 255; 92 else 93 return val; 94} 95 96 97#define STENCIL_OP(NEW_VAL) \ 98 if (invmask == 0) { \ 99 for (i = j = 0; i < n; i++, j += stride) { \ 100 if (mask[i]) { \ 101 GLubyte s = stencil[j]; \ 102 (void) s; \ 103 stencil[j] = (GLubyte) (NEW_VAL); \ 104 } \ 105 } \ 106 } \ 107 else { \ 108 for (i = j = 0; i < n; i++, j += stride) { \ 109 if (mask[i]) { \ 110 GLubyte s = stencil[j]; \ 111 stencil[j] = (GLubyte) ((invmask & s) | (wrtmask & (NEW_VAL))); \ 112 } \ 113 } \ 114 } 115 116 117/** 118 * Apply the given stencil operator to the array of stencil values. 119 * Don't touch stencil[i] if mask[i] is zero. 120 * @param n number of stencil values 121 * @param oper the stencil buffer operator 122 * @param face 0 or 1 for front or back face operation 123 * @param stencil array of stencil values (in/out) 124 * @param mask array [n] of flag: 1=apply operator, 0=don't apply operator 125 * @param stride stride between stencil values 126 */ 127static void 128apply_stencil_op(const struct gl_context *ctx, GLenum oper, GLuint face, 129 GLuint n, GLubyte stencil[], const GLubyte mask[], 130 GLint stride) 131{ 132 const GLubyte ref = _mesa_get_stencil_ref(ctx, face); 133 const GLubyte wrtmask = ctx->Stencil.WriteMask[face]; 134 const GLubyte invmask = (GLubyte) (~wrtmask); 135 GLuint i, j; 136 137 switch (oper) { 138 case GL_KEEP: 139 /* do nothing */ 140 break; 141 case GL_ZERO: 142 /* replace stencil buf values with zero */ 143 STENCIL_OP(0); 144 break; 145 case GL_REPLACE: 146 /* replace stencil buf values with ref value */ 147 STENCIL_OP(ref); 148 break; 149 case GL_INCR: 150 /* increment stencil buf values, with clamping */ 151 STENCIL_OP(clamp(s + 1)); 152 break; 153 case GL_DECR: 154 /* increment stencil buf values, with clamping */ 155 STENCIL_OP(clamp(s - 1)); 156 break; 157 case GL_INCR_WRAP_EXT: 158 /* increment stencil buf values, without clamping */ 159 STENCIL_OP(s + 1); 160 break; 161 case GL_DECR_WRAP_EXT: 162 /* increment stencil buf values, without clamping */ 163 STENCIL_OP(s - 1); 164 break; 165 case GL_INVERT: 166 /* replace stencil buf values with inverted value */ 167 STENCIL_OP(~s); 168 break; 169 default: 170 _mesa_problem(ctx, "Bad stencil op in apply_stencil_op"); 171 } 172} 173 174 175 176#define STENCIL_TEST(FUNC) \ 177 for (i = j = 0; i < n; i++, j += stride) { \ 178 if (mask[i]) { \ 179 s = (GLubyte) (stencil[j] & valueMask); \ 180 if (FUNC) { \ 181 /* stencil pass */ \ 182 fail[i] = 0; \ 183 } \ 184 else { \ 185 /* stencil fail */ \ 186 fail[i] = 1; \ 187 mask[i] = 0; \ 188 } \ 189 } \ 190 else { \ 191 fail[i] = 0; \ 192 } \ 193 } 194 195 196 197/** 198 * Apply stencil test to an array of stencil values (before depth buffering). 199 * For the values that fail, we'll apply the GL_STENCIL_FAIL operator to 200 * the stencil values. 201 * 202 * @param face 0 or 1 for front or back-face polygons 203 * @param n number of pixels in the array 204 * @param stencil array of [n] stencil values (in/out) 205 * @param mask array [n] of flag: 0=skip the pixel, 1=stencil the pixel, 206 * values are set to zero where the stencil test fails. 207 * @param stride stride between stencil values 208 * @return GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. 209 */ 210static GLboolean 211do_stencil_test(struct gl_context *ctx, GLuint face, GLuint n, 212 GLubyte stencil[], GLubyte mask[], GLint stride) 213{ 214 SWcontext *swrast = SWRAST_CONTEXT(ctx); 215 GLubyte *fail = swrast->stencil_temp.buf2; 216 GLboolean allfail = GL_FALSE; 217 GLuint i, j; 218 const GLuint valueMask = ctx->Stencil.ValueMask[face]; 219 const GLubyte ref = (GLubyte) (_mesa_get_stencil_ref(ctx, face) & valueMask); 220 GLubyte s; 221 222 /* 223 * Perform stencil test. The results of this operation are stored 224 * in the fail[] array: 225 * IF fail[i] is non-zero THEN 226 * the stencil fail operator is to be applied 227 * ELSE 228 * the stencil fail operator is not to be applied 229 * ENDIF 230 */ 231 switch (ctx->Stencil.Function[face]) { 232 case GL_NEVER: 233 STENCIL_TEST(0); 234 allfail = GL_TRUE; 235 break; 236 case GL_LESS: 237 STENCIL_TEST(ref < s); 238 break; 239 case GL_LEQUAL: 240 STENCIL_TEST(ref <= s); 241 break; 242 case GL_GREATER: 243 STENCIL_TEST(ref > s); 244 break; 245 case GL_GEQUAL: 246 STENCIL_TEST(ref >= s); 247 break; 248 case GL_EQUAL: 249 STENCIL_TEST(ref == s); 250 break; 251 case GL_NOTEQUAL: 252 STENCIL_TEST(ref != s); 253 break; 254 case GL_ALWAYS: 255 STENCIL_TEST(1); 256 break; 257 default: 258 _mesa_problem(ctx, "Bad stencil func in gl_stencil_span"); 259 return 0; 260 } 261 262 if (ctx->Stencil.FailFunc[face] != GL_KEEP) { 263 apply_stencil_op(ctx, ctx->Stencil.FailFunc[face], face, n, stencil, 264 fail, stride); 265 } 266 267 return !allfail; 268} 269 270 271/** 272 * Compute the zpass/zfail masks by comparing the pre- and post-depth test 273 * masks. 274 */ 275static inline void 276compute_pass_fail_masks(GLuint n, const GLubyte origMask[], 277 const GLubyte newMask[], 278 GLubyte passMask[], GLubyte failMask[]) 279{ 280 GLuint i; 281 for (i = 0; i < n; i++) { 282 assert(newMask[i] == 0 || newMask[i] == 1); 283 passMask[i] = origMask[i] & newMask[i]; 284 failMask[i] = origMask[i] & (newMask[i] ^ 1); 285 } 286} 287 288 289/** 290 * Get 8-bit stencil values from random locations in the stencil buffer. 291 */ 292static void 293get_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 294 GLuint count, const GLint x[], const GLint y[], 295 GLubyte stencil[]) 296{ 297 struct swrast_renderbuffer *srb = swrast_renderbuffer(rb); 298 const GLint w = rb->Width, h = rb->Height; 299 const GLubyte *map = _swrast_pixel_address(rb, 0, 0); 300 GLuint i; 301 302 if (rb->Format == MESA_FORMAT_S_UINT8) { 303 const GLint rowStride = srb->RowStride; 304 for (i = 0; i < count; i++) { 305 if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 306 stencil[i] = *(map + y[i] * rowStride + x[i]); 307 } 308 } 309 } 310 else { 311 const GLint bpp = _mesa_get_format_bytes(rb->Format); 312 const GLint rowStride = srb->RowStride; 313 for (i = 0; i < count; i++) { 314 if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 315 const GLubyte *src = map + y[i] * rowStride + x[i] * bpp; 316 _mesa_unpack_ubyte_stencil_row(rb->Format, 1, src, &stencil[i]); 317 } 318 } 319 } 320} 321 322 323 324/** 325 ** Pack ubyte stencil pixels 326 **/ 327 328static void 329pack_ubyte_stencil_Z24_S8(const uint8_t *src, void *dst) 330{ 331 /* don't disturb the Z values */ 332 uint32_t *d = ((uint32_t *) dst); 333 uint32_t s = *src; 334 uint32_t z = *d & 0xffffff00; 335 *d = z | s; 336} 337 338static void 339pack_ubyte_stencil_S8_Z24(const uint8_t *src, void *dst) 340{ 341 /* don't disturb the Z values */ 342 uint32_t *d = ((uint32_t *) dst); 343 uint32_t s = *src << 24; 344 uint32_t z = *d & 0xffffff; 345 *d = s | z; 346} 347 348static void 349pack_ubyte_stencil_S8(const uint8_t *src, void *dst) 350{ 351 uint8_t *d = (uint8_t *) dst; 352 *d = *src; 353} 354 355static void 356pack_ubyte_stencil_Z32_FLOAT_X24S8(const uint8_t *src, void *dst) 357{ 358 float *d = ((float *) dst); 359 d[1] = *src; 360} 361 362/** Pack a uint8_t stencil value to dest address */ 363typedef void (*mesa_pack_ubyte_stencil_func)(const uint8_t *src, void *dst); 364 365static mesa_pack_ubyte_stencil_func 366get_pack_ubyte_stencil_func(mesa_format format) 367{ 368 switch (format) { 369 case MESA_FORMAT_S8_UINT_Z24_UNORM: 370 return pack_ubyte_stencil_Z24_S8; 371 case MESA_FORMAT_Z24_UNORM_S8_UINT: 372 return pack_ubyte_stencil_S8_Z24; 373 case MESA_FORMAT_S_UINT8: 374 return pack_ubyte_stencil_S8; 375 case MESA_FORMAT_Z32_FLOAT_S8X24_UINT: 376 return pack_ubyte_stencil_Z32_FLOAT_X24S8; 377 default: 378 unreachable("unexpected format in get_pack_ubyte_stencil_func()"); 379 } 380} 381 382 383/** 384 * Put 8-bit stencil values at random locations into the stencil buffer. 385 */ 386static void 387put_s8_values(struct gl_context *ctx, struct gl_renderbuffer *rb, 388 GLuint count, const GLint x[], const GLint y[], 389 const GLubyte stencil[]) 390{ 391 const GLint w = rb->Width, h = rb->Height; 392 mesa_pack_ubyte_stencil_func pack_stencil = 393 get_pack_ubyte_stencil_func(rb->Format); 394 GLuint i; 395 396 for (i = 0; i < count; i++) { 397 if (x[i] >= 0 && y[i] >= 0 && x[i] < w && y[i] < h) { 398 GLubyte *dst = _swrast_pixel_address(rb, x[i], y[i]); 399 pack_stencil(&stencil[i], dst); 400 } 401 } 402} 403 404 405/** 406 * /return GL_TRUE = one or more fragments passed, 407 * GL_FALSE = all fragments failed. 408 */ 409GLboolean 410_swrast_stencil_and_ztest_span(struct gl_context *ctx, SWspan *span) 411{ 412 SWcontext *swrast = SWRAST_CONTEXT(ctx); 413 struct gl_framebuffer *fb = ctx->DrawBuffer; 414 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 415 const GLint stencilOffset = get_stencil_offset(rb->Format); 416 const GLint stencilStride = _mesa_get_format_bytes(rb->Format); 417 const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace; 418 const GLuint count = span->end; 419 GLubyte *mask = span->array->mask; 420 GLubyte *stencilTemp = swrast->stencil_temp.buf1; 421 GLubyte *stencilBuf; 422 423 if (span->arrayMask & SPAN_XY) { 424 /* read stencil values from random locations */ 425 get_s8_values(ctx, rb, count, span->array->x, span->array->y, 426 stencilTemp); 427 stencilBuf = stencilTemp; 428 } 429 else { 430 /* Processing a horizontal run of pixels. Since stencil is always 431 * 8 bits for all MESA_FORMATs, we just need to use the right offset 432 * and stride to access them. 433 */ 434 stencilBuf = _swrast_pixel_address(rb, span->x, span->y) + stencilOffset; 435 } 436 437 /* 438 * Apply the stencil test to the fragments. 439 * failMask[i] is 1 if the stencil test failed. 440 */ 441 if (!do_stencil_test(ctx, face, count, stencilBuf, mask, stencilStride)) { 442 /* all fragments failed the stencil test, we're done. */ 443 span->writeAll = GL_FALSE; 444 if (span->arrayMask & SPAN_XY) { 445 /* need to write the updated stencil values back to the buffer */ 446 put_s8_values(ctx, rb, count, span->array->x, span->array->y, 447 stencilTemp); 448 } 449 return GL_FALSE; 450 } 451 452 /* 453 * Some fragments passed the stencil test, apply depth test to them 454 * and apply Zpass and Zfail stencil ops. 455 */ 456 if (ctx->Depth.Test == GL_FALSE || 457 ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer == NULL) { 458 /* 459 * No depth buffer, just apply zpass stencil function to active pixels. 460 */ 461 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, count, 462 stencilBuf, mask, stencilStride); 463 } 464 else { 465 /* 466 * Perform depth buffering, then apply zpass or zfail stencil function. 467 */ 468 SWcontext *swrast = SWRAST_CONTEXT(ctx); 469 GLubyte *passMask = swrast->stencil_temp.buf2; 470 GLubyte *failMask = swrast->stencil_temp.buf3; 471 GLubyte *origMask = swrast->stencil_temp.buf4; 472 473 /* save the current mask bits */ 474 memcpy(origMask, mask, count * sizeof(GLubyte)); 475 476 /* apply the depth test */ 477 _swrast_depth_test_span(ctx, span); 478 479 compute_pass_fail_masks(count, origMask, mask, passMask, failMask); 480 481 /* apply the pass and fail operations */ 482 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { 483 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face, 484 count, stencilBuf, failMask, stencilStride); 485 } 486 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { 487 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, 488 count, stencilBuf, passMask, stencilStride); 489 } 490 } 491 492 /* Write updated stencil values back into hardware stencil buffer */ 493 if (span->arrayMask & SPAN_XY) { 494 put_s8_values(ctx, rb, count, span->array->x, span->array->y, 495 stencilBuf); 496 } 497 498 span->writeAll = GL_FALSE; 499 500 return GL_TRUE; /* one or more fragments passed both tests */ 501} 502 503 504 505 506/** 507 * Return a span of stencil values from the stencil buffer. 508 * Used for glRead/CopyPixels 509 * Input: n - how many pixels 510 * x,y - location of first pixel 511 * Output: stencil - the array of stencil values 512 */ 513void 514_swrast_read_stencil_span(struct gl_context *ctx, struct gl_renderbuffer *rb, 515 GLint n, GLint x, GLint y, GLubyte stencil[]) 516{ 517 GLubyte *src; 518 519 if (y < 0 || y >= (GLint) rb->Height || 520 x + n <= 0 || x >= (GLint) rb->Width) { 521 /* span is completely outside framebuffer */ 522 return; /* undefined values OK */ 523 } 524 525 if (x < 0) { 526 GLint dx = -x; 527 x = 0; 528 n -= dx; 529 stencil += dx; 530 } 531 if (x + n > (GLint) rb->Width) { 532 GLint dx = x + n - rb->Width; 533 n -= dx; 534 } 535 if (n <= 0) { 536 return; 537 } 538 539 src = _swrast_pixel_address(rb, x, y); 540 _mesa_unpack_ubyte_stencil_row(rb->Format, n, src, stencil); 541} 542 543 544 545/** 546 * Write a span of stencil values to the stencil buffer. This function 547 * applies the stencil write mask when needed. 548 * Used for glDraw/CopyPixels 549 * Input: n - how many pixels 550 * x, y - location of first pixel 551 * stencil - the array of stencil values 552 */ 553void 554_swrast_write_stencil_span(struct gl_context *ctx, GLint n, GLint x, GLint y, 555 const GLubyte stencil[] ) 556{ 557 SWcontext *swrast = SWRAST_CONTEXT(ctx); 558 struct gl_framebuffer *fb = ctx->DrawBuffer; 559 struct gl_renderbuffer *rb = fb->Attachment[BUFFER_STENCIL].Renderbuffer; 560 const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1; 561 const GLuint stencilMask = ctx->Stencil.WriteMask[0]; 562 GLubyte *stencilBuf; 563 564 if (y < 0 || y >= (GLint) rb->Height || 565 x + n <= 0 || x >= (GLint) rb->Width) { 566 /* span is completely outside framebuffer */ 567 return; /* undefined values OK */ 568 } 569 if (x < 0) { 570 GLint dx = -x; 571 x = 0; 572 n -= dx; 573 stencil += dx; 574 } 575 if (x + n > (GLint) rb->Width) { 576 GLint dx = x + n - rb->Width; 577 n -= dx; 578 } 579 if (n <= 0) { 580 return; 581 } 582 583 stencilBuf = _swrast_pixel_address(rb, x, y); 584 585 if ((stencilMask & stencilMax) != stencilMax) { 586 /* need to apply writemask */ 587 GLubyte *destVals = swrast->stencil_temp.buf1; 588 GLubyte *newVals = swrast->stencil_temp.buf2; 589 GLint i; 590 591 _mesa_unpack_ubyte_stencil_row(rb->Format, n, stencilBuf, destVals); 592 for (i = 0; i < n; i++) { 593 newVals[i] 594 = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask); 595 } 596 _mesa_pack_ubyte_stencil_row(rb->Format, n, newVals, stencilBuf); 597 } 598 else { 599 _mesa_pack_ubyte_stencil_row(rb->Format, n, stencil, stencilBuf); 600 } 601} 602 603 604 605/** 606 * Clear the stencil buffer. If the buffer is a combined 607 * depth+stencil buffer, only the stencil bits will be touched. 608 */ 609void 610_swrast_clear_stencil_buffer(struct gl_context *ctx) 611{ 612 struct gl_renderbuffer *rb = 613 ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; 614 const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; 615 const GLuint writeMask = ctx->Stencil.WriteMask[0]; 616 const GLuint stencilMax = (1 << stencilBits) - 1; 617 GLint x, y, width, height; 618 GLubyte *map; 619 GLint rowStride, i, j; 620 GLbitfield mapMode; 621 622 if (!rb || writeMask == 0) 623 return; 624 625 /* compute region to clear */ 626 x = ctx->DrawBuffer->_Xmin; 627 y = ctx->DrawBuffer->_Ymin; 628 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 629 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 630 631 mapMode = GL_MAP_WRITE_BIT; 632 if ((writeMask & stencilMax) != stencilMax) { 633 /* need to mask stencil values */ 634 mapMode |= GL_MAP_READ_BIT; 635 } 636 else if (_mesa_get_format_bits(rb->Format, GL_DEPTH_BITS) > 0) { 637 /* combined depth+stencil, need to mask Z values */ 638 mapMode |= GL_MAP_READ_BIT; 639 } 640 641 ctx->Driver.MapRenderbuffer(ctx, rb, x, y, width, height, 642 mapMode, &map, &rowStride, 643 ctx->DrawBuffer->FlipY); 644 if (!map) { 645 _mesa_error(ctx, GL_OUT_OF_MEMORY, "glClear(stencil)"); 646 return; 647 } 648 649 switch (rb->Format) { 650 case MESA_FORMAT_S_UINT8: 651 { 652 GLubyte clear = ctx->Stencil.Clear & writeMask & 0xff; 653 GLubyte mask = (~writeMask) & 0xff; 654 if (mask != 0) { 655 /* masked clear */ 656 for (i = 0; i < height; i++) { 657 GLubyte *row = map; 658 for (j = 0; j < width; j++) { 659 row[j] = (row[j] & mask) | clear; 660 } 661 map += rowStride; 662 } 663 } 664 else if (rowStride == width) { 665 /* clear whole buffer */ 666 memset(map, clear, width * height); 667 } 668 else { 669 /* clear scissored */ 670 for (i = 0; i < height; i++) { 671 memset(map, clear, width); 672 map += rowStride; 673 } 674 } 675 } 676 break; 677 case MESA_FORMAT_Z24_UNORM_S8_UINT: 678 { 679 GLuint clear = (ctx->Stencil.Clear & writeMask & 0xff) << 24; 680 GLuint mask = (((~writeMask) & 0xff) << 24) | 0xffffff; 681 for (i = 0; i < height; i++) { 682 GLuint *row = (GLuint *) map; 683 for (j = 0; j < width; j++) { 684 row[j] = (row[j] & mask) | clear; 685 } 686 map += rowStride; 687 } 688 } 689 break; 690 case MESA_FORMAT_S8_UINT_Z24_UNORM: 691 { 692 GLuint clear = ctx->Stencil.Clear & writeMask & 0xff; 693 GLuint mask = 0xffffff00 | ((~writeMask) & 0xff); 694 for (i = 0; i < height; i++) { 695 GLuint *row = (GLuint *) map; 696 for (j = 0; j < width; j++) { 697 row[j] = (row[j] & mask) | clear; 698 } 699 map += rowStride; 700 } 701 } 702 break; 703 default: 704 _mesa_problem(ctx, "Unexpected stencil buffer format %s" 705 " in _swrast_clear_stencil_buffer()", 706 _mesa_get_format_name(rb->Format)); 707 } 708 709 ctx->Driver.UnmapRenderbuffer(ctx, rb); 710} 711