Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygens_stencil.c
Go to the documentation of this file.
00001 /* 00002 * Mesa 3-D graphics library 00003 * Version: 7.1 00004 * 00005 * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a 00008 * copy of this software and associated documentation files (the "Software"), 00009 * to deal in the Software without restriction, including without limitation 00010 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 00011 * and/or sell copies of the Software, and to permit persons to whom the 00012 * Software is furnished to do so, subject to the following conditions: 00013 * 00014 * The above copyright notice and this permission notice shall be included 00015 * in all copies or substantial portions of the Software. 00016 * 00017 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 00018 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00019 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 00020 * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 00021 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 00022 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00023 */ 00024 00025 00026 #include "main/glheader.h" 00027 #include "main/context.h" 00028 #include "main/imports.h" 00029 00030 #include "s_context.h" 00031 #include "s_depth.h" 00032 #include "s_stencil.h" 00033 #include "s_span.h" 00034 00035 00036 00037 /* Stencil Logic: 00038 00039 IF stencil test fails THEN 00040 Apply fail-op to stencil value 00041 Don't write the pixel (RGBA,Z) 00042 ELSE 00043 IF doing depth test && depth test fails THEN 00044 Apply zfail-op to stencil value 00045 Write RGBA and Z to appropriate buffers 00046 ELSE 00047 Apply zpass-op to stencil value 00048 ENDIF 00049 00050 */ 00051 00052 00063 static void 00064 apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face, 00065 GLuint n, GLstencil stencil[], const GLubyte mask[] ) 00066 { 00067 const GLstencil ref = ctx->Stencil.Ref[face]; 00068 const GLstencil wrtmask = ctx->Stencil.WriteMask[face]; 00069 const GLstencil invmask = (GLstencil) (~wrtmask); 00070 const GLstencil stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; 00071 GLuint i; 00072 00073 switch (oper) { 00074 case GL_KEEP: 00075 /* do nothing */ 00076 break; 00077 case GL_ZERO: 00078 if (invmask==0) { 00079 for (i=0;i<n;i++) { 00080 if (mask[i]) { 00081 stencil[i] = 0; 00082 } 00083 } 00084 } 00085 else { 00086 for (i=0;i<n;i++) { 00087 if (mask[i]) { 00088 stencil[i] = (GLstencil) (stencil[i] & invmask); 00089 } 00090 } 00091 } 00092 break; 00093 case GL_REPLACE: 00094 if (invmask==0) { 00095 for (i=0;i<n;i++) { 00096 if (mask[i]) { 00097 stencil[i] = ref; 00098 } 00099 } 00100 } 00101 else { 00102 for (i=0;i<n;i++) { 00103 if (mask[i]) { 00104 GLstencil s = stencil[i]; 00105 stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref)); 00106 } 00107 } 00108 } 00109 break; 00110 case GL_INCR: 00111 if (invmask==0) { 00112 for (i=0;i<n;i++) { 00113 if (mask[i]) { 00114 GLstencil s = stencil[i]; 00115 if (s < stencilMax) { 00116 stencil[i] = (GLstencil) (s+1); 00117 } 00118 } 00119 } 00120 } 00121 else { 00122 for (i=0;i<n;i++) { 00123 if (mask[i]) { 00124 /* VERIFY logic of adding 1 to a write-masked value */ 00125 GLstencil s = stencil[i]; 00126 if (s < stencilMax) { 00127 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1))); 00128 } 00129 } 00130 } 00131 } 00132 break; 00133 case GL_DECR: 00134 if (invmask==0) { 00135 for (i=0;i<n;i++) { 00136 if (mask[i]) { 00137 GLstencil s = stencil[i]; 00138 if (s>0) { 00139 stencil[i] = (GLstencil) (s-1); 00140 } 00141 } 00142 } 00143 } 00144 else { 00145 for (i=0;i<n;i++) { 00146 if (mask[i]) { 00147 /* VERIFY logic of subtracting 1 to a write-masked value */ 00148 GLstencil s = stencil[i]; 00149 if (s>0) { 00150 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1))); 00151 } 00152 } 00153 } 00154 } 00155 break; 00156 case GL_INCR_WRAP_EXT: 00157 if (invmask==0) { 00158 for (i=0;i<n;i++) { 00159 if (mask[i]) { 00160 stencil[i]++; 00161 } 00162 } 00163 } 00164 else { 00165 for (i=0;i<n;i++) { 00166 if (mask[i]) { 00167 GLstencil s = stencil[i]; 00168 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1))); 00169 } 00170 } 00171 } 00172 break; 00173 case GL_DECR_WRAP_EXT: 00174 if (invmask==0) { 00175 for (i=0;i<n;i++) { 00176 if (mask[i]) { 00177 stencil[i]--; 00178 } 00179 } 00180 } 00181 else { 00182 for (i=0;i<n;i++) { 00183 if (mask[i]) { 00184 GLstencil s = stencil[i]; 00185 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1))); 00186 } 00187 } 00188 } 00189 break; 00190 case GL_INVERT: 00191 if (invmask==0) { 00192 for (i=0;i<n;i++) { 00193 if (mask[i]) { 00194 GLstencil s = stencil[i]; 00195 stencil[i] = (GLstencil) ~s; 00196 } 00197 } 00198 } 00199 else { 00200 for (i=0;i<n;i++) { 00201 if (mask[i]) { 00202 GLstencil s = stencil[i]; 00203 stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s)); 00204 } 00205 } 00206 } 00207 break; 00208 default: 00209 _mesa_problem(ctx, "Bad stencil op in apply_stencil_op"); 00210 } 00211 } 00212 00213 00214 00215 00227 static GLboolean 00228 do_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[], 00229 GLubyte mask[] ) 00230 { 00231 GLubyte fail[MAX_WIDTH]; 00232 GLboolean allfail = GL_FALSE; 00233 GLuint i; 00234 GLstencil r, s; 00235 const GLuint valueMask = ctx->Stencil.ValueMask[face]; 00236 00237 ASSERT(n <= MAX_WIDTH); 00238 00239 /* 00240 * Perform stencil test. The results of this operation are stored 00241 * in the fail[] array: 00242 * IF fail[i] is non-zero THEN 00243 * the stencil fail operator is to be applied 00244 * ELSE 00245 * the stencil fail operator is not to be applied 00246 * ENDIF 00247 */ 00248 switch (ctx->Stencil.Function[face]) { 00249 case GL_NEVER: 00250 /* never pass; always fail */ 00251 for (i=0;i<n;i++) { 00252 if (mask[i]) { 00253 mask[i] = 0; 00254 fail[i] = 1; 00255 } 00256 else { 00257 fail[i] = 0; 00258 } 00259 } 00260 allfail = GL_TRUE; 00261 break; 00262 case GL_LESS: 00263 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00264 for (i=0;i<n;i++) { 00265 if (mask[i]) { 00266 s = (GLstencil) (stencil[i] & valueMask); 00267 if (r < s) { 00268 /* passed */ 00269 fail[i] = 0; 00270 } 00271 else { 00272 fail[i] = 1; 00273 mask[i] = 0; 00274 } 00275 } 00276 else { 00277 fail[i] = 0; 00278 } 00279 } 00280 break; 00281 case GL_LEQUAL: 00282 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00283 for (i=0;i<n;i++) { 00284 if (mask[i]) { 00285 s = (GLstencil) (stencil[i] & valueMask); 00286 if (r <= s) { 00287 /* pass */ 00288 fail[i] = 0; 00289 } 00290 else { 00291 fail[i] = 1; 00292 mask[i] = 0; 00293 } 00294 } 00295 else { 00296 fail[i] = 0; 00297 } 00298 } 00299 break; 00300 case GL_GREATER: 00301 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00302 for (i=0;i<n;i++) { 00303 if (mask[i]) { 00304 s = (GLstencil) (stencil[i] & valueMask); 00305 if (r > s) { 00306 /* passed */ 00307 fail[i] = 0; 00308 } 00309 else { 00310 fail[i] = 1; 00311 mask[i] = 0; 00312 } 00313 } 00314 else { 00315 fail[i] = 0; 00316 } 00317 } 00318 break; 00319 case GL_GEQUAL: 00320 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00321 for (i=0;i<n;i++) { 00322 if (mask[i]) { 00323 s = (GLstencil) (stencil[i] & valueMask); 00324 if (r >= s) { 00325 /* passed */ 00326 fail[i] = 0; 00327 } 00328 else { 00329 fail[i] = 1; 00330 mask[i] = 0; 00331 } 00332 } 00333 else { 00334 fail[i] = 0; 00335 } 00336 } 00337 break; 00338 case GL_EQUAL: 00339 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00340 for (i=0;i<n;i++) { 00341 if (mask[i]) { 00342 s = (GLstencil) (stencil[i] & valueMask); 00343 if (r == s) { 00344 /* passed */ 00345 fail[i] = 0; 00346 } 00347 else { 00348 fail[i] = 1; 00349 mask[i] = 0; 00350 } 00351 } 00352 else { 00353 fail[i] = 0; 00354 } 00355 } 00356 break; 00357 case GL_NOTEQUAL: 00358 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00359 for (i=0;i<n;i++) { 00360 if (mask[i]) { 00361 s = (GLstencil) (stencil[i] & valueMask); 00362 if (r != s) { 00363 /* passed */ 00364 fail[i] = 0; 00365 } 00366 else { 00367 fail[i] = 1; 00368 mask[i] = 0; 00369 } 00370 } 00371 else { 00372 fail[i] = 0; 00373 } 00374 } 00375 break; 00376 case GL_ALWAYS: 00377 /* always pass */ 00378 for (i=0;i<n;i++) { 00379 fail[i] = 0; 00380 } 00381 break; 00382 default: 00383 _mesa_problem(ctx, "Bad stencil func in gl_stencil_span"); 00384 return 0; 00385 } 00386 00387 if (ctx->Stencil.FailFunc[face] != GL_KEEP) { 00388 apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail ); 00389 } 00390 00391 return !allfail; 00392 } 00393 00394 00399 static INLINE void 00400 compute_pass_fail_masks(GLuint n, const GLubyte origMask[], 00401 const GLubyte newMask[], 00402 GLubyte passMask[], GLubyte failMask[]) 00403 { 00404 GLuint i; 00405 for (i = 0; i < n; i++) { 00406 ASSERT(newMask[i] == 0 || newMask[i] == 1); 00407 passMask[i] = origMask[i] & newMask[i]; 00408 failMask[i] = origMask[i] & (newMask[i] ^ 1); 00409 } 00410 } 00411 00412 00425 static GLboolean 00426 stencil_and_ztest_span(GLcontext *ctx, SWspan *span, GLuint face) 00427 { 00428 struct gl_framebuffer *fb = ctx->DrawBuffer; 00429 struct gl_renderbuffer *rb = fb->_StencilBuffer; 00430 GLstencil stencilRow[MAX_WIDTH]; 00431 GLstencil *stencil; 00432 const GLuint n = span->end; 00433 const GLint x = span->x; 00434 const GLint y = span->y; 00435 GLubyte *mask = span->array->mask; 00436 00437 ASSERT((span->arrayMask & SPAN_XY) == 0); 00438 ASSERT(ctx->Stencil.Enabled); 00439 ASSERT(n <= MAX_WIDTH); 00440 #ifdef DEBUG 00441 if (ctx->Depth.Test) { 00442 ASSERT(span->arrayMask & SPAN_Z); 00443 } 00444 #endif 00445 00446 stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y); 00447 if (!stencil) { 00448 rb->GetRow(ctx, rb, n, x, y, stencilRow); 00449 stencil = stencilRow; 00450 } 00451 00452 /* 00453 * Apply the stencil test to the fragments. 00454 * failMask[i] is 1 if the stencil test failed. 00455 */ 00456 if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) { 00457 /* all fragments failed the stencil test, we're done. */ 00458 span->writeAll = GL_FALSE; 00459 if (!rb->GetPointer(ctx, rb, 0, 0)) { 00460 /* put updated stencil values into buffer */ 00461 rb->PutRow(ctx, rb, n, x, y, stencil, NULL); 00462 } 00463 return GL_FALSE; 00464 } 00465 00466 /* 00467 * Some fragments passed the stencil test, apply depth test to them 00468 * and apply Zpass and Zfail stencil ops. 00469 */ 00470 if (ctx->Depth.Test == GL_FALSE) { 00471 /* 00472 * No depth buffer, just apply zpass stencil function to active pixels. 00473 */ 00474 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask ); 00475 } 00476 else { 00477 /* 00478 * Perform depth buffering, then apply zpass or zfail stencil function. 00479 */ 00480 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH]; 00481 00482 /* save the current mask bits */ 00483 _mesa_memcpy(origMask, mask, n * sizeof(GLubyte)); 00484 00485 /* apply the depth test */ 00486 _swrast_depth_test_span(ctx, span); 00487 00488 compute_pass_fail_masks(n, origMask, mask, passMask, failMask); 00489 00490 /* apply the pass and fail operations */ 00491 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { 00492 apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face, 00493 n, stencil, failMask ); 00494 } 00495 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { 00496 apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, 00497 n, stencil, passMask ); 00498 } 00499 } 00500 00501 /* 00502 * Write updated stencil values back into hardware stencil buffer. 00503 */ 00504 if (!rb->GetPointer(ctx, rb, 0, 0)) { 00505 rb->PutRow(ctx, rb, n, x, y, stencil, NULL); 00506 } 00507 00508 span->writeAll = GL_FALSE; 00509 00510 return GL_TRUE; /* one or more fragments passed both tests */ 00511 } 00512 00513 00514 00515 /* 00516 * Return the address of a stencil buffer value given the window coords: 00517 */ 00518 #define STENCIL_ADDRESS(X, Y) (stencilStart + (Y) * stride + (X)) 00519 00520 00521 00531 static void 00532 apply_stencil_op_to_pixels( GLcontext *ctx, 00533 GLuint n, const GLint x[], const GLint y[], 00534 GLenum oper, GLuint face, const GLubyte mask[] ) 00535 { 00536 struct gl_framebuffer *fb = ctx->DrawBuffer; 00537 struct gl_renderbuffer *rb = fb->_StencilBuffer; 00538 const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1; 00539 const GLstencil ref = ctx->Stencil.Ref[face]; 00540 const GLstencil wrtmask = ctx->Stencil.WriteMask[face]; 00541 const GLstencil invmask = (GLstencil) (~wrtmask); 00542 GLuint i; 00543 GLstencil *stencilStart = (GLubyte *) rb->Data; 00544 const GLuint stride = rb->Width; 00545 00546 ASSERT(rb->GetPointer(ctx, rb, 0, 0)); 00547 ASSERT(sizeof(GLstencil) == 1); 00548 00549 switch (oper) { 00550 case GL_KEEP: 00551 /* do nothing */ 00552 break; 00553 case GL_ZERO: 00554 if (invmask==0) { 00555 for (i=0;i<n;i++) { 00556 if (mask[i]) { 00557 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00558 *sptr = 0; 00559 } 00560 } 00561 } 00562 else { 00563 for (i=0;i<n;i++) { 00564 if (mask[i]) { 00565 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00566 *sptr = (GLstencil) (invmask & *sptr); 00567 } 00568 } 00569 } 00570 break; 00571 case GL_REPLACE: 00572 if (invmask==0) { 00573 for (i=0;i<n;i++) { 00574 if (mask[i]) { 00575 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00576 *sptr = ref; 00577 } 00578 } 00579 } 00580 else { 00581 for (i=0;i<n;i++) { 00582 if (mask[i]) { 00583 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00584 *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref)); 00585 } 00586 } 00587 } 00588 break; 00589 case GL_INCR: 00590 if (invmask==0) { 00591 for (i=0;i<n;i++) { 00592 if (mask[i]) { 00593 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00594 if (*sptr < stencilMax) { 00595 *sptr = (GLstencil) (*sptr + 1); 00596 } 00597 } 00598 } 00599 } 00600 else { 00601 for (i=0;i<n;i++) { 00602 if (mask[i]) { 00603 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00604 if (*sptr < stencilMax) { 00605 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1))); 00606 } 00607 } 00608 } 00609 } 00610 break; 00611 case GL_DECR: 00612 if (invmask==0) { 00613 for (i=0;i<n;i++) { 00614 if (mask[i]) { 00615 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00616 if (*sptr>0) { 00617 *sptr = (GLstencil) (*sptr - 1); 00618 } 00619 } 00620 } 00621 } 00622 else { 00623 for (i=0;i<n;i++) { 00624 if (mask[i]) { 00625 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00626 if (*sptr>0) { 00627 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1))); 00628 } 00629 } 00630 } 00631 } 00632 break; 00633 case GL_INCR_WRAP_EXT: 00634 if (invmask==0) { 00635 for (i=0;i<n;i++) { 00636 if (mask[i]) { 00637 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00638 *sptr = (GLstencil) (*sptr + 1); 00639 } 00640 } 00641 } 00642 else { 00643 for (i=0;i<n;i++) { 00644 if (mask[i]) { 00645 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00646 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1))); 00647 } 00648 } 00649 } 00650 break; 00651 case GL_DECR_WRAP_EXT: 00652 if (invmask==0) { 00653 for (i=0;i<n;i++) { 00654 if (mask[i]) { 00655 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00656 *sptr = (GLstencil) (*sptr - 1); 00657 } 00658 } 00659 } 00660 else { 00661 for (i=0;i<n;i++) { 00662 if (mask[i]) { 00663 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00664 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1))); 00665 } 00666 } 00667 } 00668 break; 00669 case GL_INVERT: 00670 if (invmask==0) { 00671 for (i=0;i<n;i++) { 00672 if (mask[i]) { 00673 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00674 *sptr = (GLstencil) (~*sptr); 00675 } 00676 } 00677 } 00678 else { 00679 for (i=0;i<n;i++) { 00680 if (mask[i]) { 00681 GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] ); 00682 *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr)); 00683 } 00684 } 00685 } 00686 break; 00687 default: 00688 _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels"); 00689 } 00690 } 00691 00692 00693 00705 static GLboolean 00706 stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n, 00707 const GLint x[], const GLint y[], GLubyte mask[] ) 00708 { 00709 const struct gl_framebuffer *fb = ctx->DrawBuffer; 00710 struct gl_renderbuffer *rb = fb->_StencilBuffer; 00711 GLubyte fail[MAX_WIDTH]; 00712 GLstencil r, s; 00713 GLuint i; 00714 GLboolean allfail = GL_FALSE; 00715 const GLuint valueMask = ctx->Stencil.ValueMask[face]; 00716 const GLstencil *stencilStart = (GLstencil *) rb->Data; 00717 const GLuint stride = rb->Width; 00718 00719 ASSERT(rb->GetPointer(ctx, rb, 0, 0)); 00720 ASSERT(sizeof(GLstencil) == 1); 00721 00722 /* 00723 * Perform stencil test. The results of this operation are stored 00724 * in the fail[] array: 00725 * IF fail[i] is non-zero THEN 00726 * the stencil fail operator is to be applied 00727 * ELSE 00728 * the stencil fail operator is not to be applied 00729 * ENDIF 00730 */ 00731 00732 switch (ctx->Stencil.Function[face]) { 00733 case GL_NEVER: 00734 /* always fail */ 00735 for (i=0;i<n;i++) { 00736 if (mask[i]) { 00737 mask[i] = 0; 00738 fail[i] = 1; 00739 } 00740 else { 00741 fail[i] = 0; 00742 } 00743 } 00744 allfail = GL_TRUE; 00745 break; 00746 case GL_LESS: 00747 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00748 for (i=0;i<n;i++) { 00749 if (mask[i]) { 00750 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 00751 s = (GLstencil) (*sptr & valueMask); 00752 if (r < s) { 00753 /* passed */ 00754 fail[i] = 0; 00755 } 00756 else { 00757 fail[i] = 1; 00758 mask[i] = 0; 00759 } 00760 } 00761 else { 00762 fail[i] = 0; 00763 } 00764 } 00765 break; 00766 case GL_LEQUAL: 00767 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00768 for (i=0;i<n;i++) { 00769 if (mask[i]) { 00770 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 00771 s = (GLstencil) (*sptr & valueMask); 00772 if (r <= s) { 00773 /* pass */ 00774 fail[i] = 0; 00775 } 00776 else { 00777 fail[i] = 1; 00778 mask[i] = 0; 00779 } 00780 } 00781 else { 00782 fail[i] = 0; 00783 } 00784 } 00785 break; 00786 case GL_GREATER: 00787 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00788 for (i=0;i<n;i++) { 00789 if (mask[i]) { 00790 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 00791 s = (GLstencil) (*sptr & valueMask); 00792 if (r > s) { 00793 /* passed */ 00794 fail[i] = 0; 00795 } 00796 else { 00797 fail[i] = 1; 00798 mask[i] = 0; 00799 } 00800 } 00801 else { 00802 fail[i] = 0; 00803 } 00804 } 00805 break; 00806 case GL_GEQUAL: 00807 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00808 for (i=0;i<n;i++) { 00809 if (mask[i]) { 00810 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 00811 s = (GLstencil) (*sptr & valueMask); 00812 if (r >= s) { 00813 /* passed */ 00814 fail[i] = 0; 00815 } 00816 else { 00817 fail[i] = 1; 00818 mask[i] = 0; 00819 } 00820 } 00821 else { 00822 fail[i] = 0; 00823 } 00824 } 00825 break; 00826 case GL_EQUAL: 00827 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00828 for (i=0;i<n;i++) { 00829 if (mask[i]) { 00830 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 00831 s = (GLstencil) (*sptr & valueMask); 00832 if (r == s) { 00833 /* passed */ 00834 fail[i] = 0; 00835 } 00836 else { 00837 fail[i] = 1; 00838 mask[i] = 0; 00839 } 00840 } 00841 else { 00842 fail[i] = 0; 00843 } 00844 } 00845 break; 00846 case GL_NOTEQUAL: 00847 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); 00848 for (i=0;i<n;i++) { 00849 if (mask[i]) { 00850 const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]); 00851 s = (GLstencil) (*sptr & valueMask); 00852 if (r != s) { 00853 /* passed */ 00854 fail[i] = 0; 00855 } 00856 else { 00857 fail[i] = 1; 00858 mask[i] = 0; 00859 } 00860 } 00861 else { 00862 fail[i] = 0; 00863 } 00864 } 00865 break; 00866 case GL_ALWAYS: 00867 /* always pass */ 00868 for (i=0;i<n;i++) { 00869 fail[i] = 0; 00870 } 00871 break; 00872 default: 00873 _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels"); 00874 return 0; 00875 } 00876 00877 if (ctx->Stencil.FailFunc[face] != GL_KEEP) { 00878 apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face], 00879 face, fail ); 00880 } 00881 00882 return !allfail; 00883 } 00884 00885 00886 00887 00904 static GLboolean 00905 stencil_and_ztest_pixels( GLcontext *ctx, SWspan *span, GLuint face ) 00906 { 00907 GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH]; 00908 struct gl_framebuffer *fb = ctx->DrawBuffer; 00909 struct gl_renderbuffer *rb = fb->_StencilBuffer; 00910 const GLuint n = span->end; 00911 const GLint *x = span->array->x; 00912 const GLint *y = span->array->y; 00913 GLubyte *mask = span->array->mask; 00914 00915 ASSERT(span->arrayMask & SPAN_XY); 00916 ASSERT(ctx->Stencil.Enabled); 00917 ASSERT(n <= MAX_WIDTH); 00918 00919 if (!rb->GetPointer(ctx, rb, 0, 0)) { 00920 /* No direct access */ 00921 GLstencil stencil[MAX_WIDTH]; 00922 00923 ASSERT(rb->DataType == GL_UNSIGNED_BYTE); 00924 _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte)); 00925 00926 _mesa_memcpy(origMask, mask, n * sizeof(GLubyte)); 00927 00928 (void) do_stencil_test(ctx, face, n, stencil, mask); 00929 00930 if (ctx->Depth.Test == GL_FALSE) { 00931 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, 00932 n, stencil, mask); 00933 } 00934 else { 00935 GLubyte tmpMask[MAX_WIDTH]; 00936 _mesa_memcpy(tmpMask, mask, n * sizeof(GLubyte)); 00937 00938 _swrast_depth_test_span(ctx, span); 00939 00940 compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask); 00941 00942 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { 00943 apply_stencil_op(ctx, ctx->Stencil.ZFailFunc[face], face, 00944 n, stencil, failMask); 00945 } 00946 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { 00947 apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face, 00948 n, stencil, passMask); 00949 } 00950 } 00951 00952 /* Write updated stencil values into hardware stencil buffer */ 00953 rb->PutValues(ctx, rb, n, x, y, stencil, origMask); 00954 00955 return GL_TRUE; 00956 } 00957 else { 00958 /* Direct access to stencil buffer */ 00959 00960 if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) { 00961 /* all fragments failed the stencil test, we're done. */ 00962 return GL_FALSE; 00963 } 00964 00965 if (ctx->Depth.Test==GL_FALSE) { 00966 apply_stencil_op_to_pixels(ctx, n, x, y, 00967 ctx->Stencil.ZPassFunc[face], face, mask); 00968 } 00969 else { 00970 _mesa_memcpy(origMask, mask, n * sizeof(GLubyte)); 00971 00972 _swrast_depth_test_span(ctx, span); 00973 00974 compute_pass_fail_masks(n, origMask, mask, passMask, failMask); 00975 00976 if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) { 00977 apply_stencil_op_to_pixels(ctx, n, x, y, 00978 ctx->Stencil.ZFailFunc[face], 00979 face, failMask); 00980 } 00981 if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) { 00982 apply_stencil_op_to_pixels(ctx, n, x, y, 00983 ctx->Stencil.ZPassFunc[face], 00984 face, passMask); 00985 } 00986 } 00987 00988 return GL_TRUE; /* one or more fragments passed both tests */ 00989 } 00990 } 00991 00992 00997 GLboolean 00998 _swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span) 00999 { 01000 const GLuint face = (span->facing == 0) ? 0 : ctx->Stencil._BackFace; 01001 01002 if (span->arrayMask & SPAN_XY) 01003 return stencil_and_ztest_pixels(ctx, span, face); 01004 else 01005 return stencil_and_ztest_span(ctx, span, face); 01006 } 01007 01008 01009 #if 0 01010 GLuint 01011 clip_span(GLuint bufferWidth, GLuint bufferHeight, 01012 GLint x, GLint y, GLuint *count) 01013 { 01014 GLuint n = *count; 01015 GLuint skipPixels = 0; 01016 01017 if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) { 01018 /* totally out of bounds */ 01019 n = 0; 01020 } 01021 else { 01022 /* left clip */ 01023 if (x < 0) { 01024 skipPixels = -x; 01025 x = 0; 01026 n -= skipPixels; 01027 } 01028 /* right clip */ 01029 if (x + n > bufferWidth) { 01030 GLint dx = x + n - bufferWidth; 01031 n -= dx; 01032 } 01033 } 01034 01035 *count = n; 01036 01037 return skipPixels; 01038 } 01039 #endif 01040 01041 01049 void 01050 _swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb, 01051 GLint n, GLint x, GLint y, GLstencil stencil[]) 01052 { 01053 if (y < 0 || y >= (GLint) rb->Height || 01054 x + n <= 0 || x >= (GLint) rb->Width) { 01055 /* span is completely outside framebuffer */ 01056 return; /* undefined values OK */ 01057 } 01058 01059 if (x < 0) { 01060 GLint dx = -x; 01061 x = 0; 01062 n -= dx; 01063 stencil += dx; 01064 } 01065 if (x + n > (GLint) rb->Width) { 01066 GLint dx = x + n - rb->Width; 01067 n -= dx; 01068 } 01069 if (n <= 0) { 01070 return; 01071 } 01072 01073 rb->GetRow(ctx, rb, n, x, y, stencil); 01074 } 01075 01076 01077 01086 void 01087 _swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y, 01088 const GLstencil stencil[] ) 01089 { 01090 struct gl_framebuffer *fb = ctx->DrawBuffer; 01091 struct gl_renderbuffer *rb = fb->_StencilBuffer; 01092 const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1; 01093 const GLuint stencilMask = ctx->Stencil.WriteMask[0]; 01094 01095 if (y < 0 || y >= (GLint) rb->Height || 01096 x + n <= 0 || x >= (GLint) rb->Width) { 01097 /* span is completely outside framebuffer */ 01098 return; /* undefined values OK */ 01099 } 01100 if (x < 0) { 01101 GLint dx = -x; 01102 x = 0; 01103 n -= dx; 01104 stencil += dx; 01105 } 01106 if (x + n > (GLint) rb->Width) { 01107 GLint dx = x + n - rb->Width; 01108 n -= dx; 01109 } 01110 if (n <= 0) { 01111 return; 01112 } 01113 01114 if ((stencilMask & stencilMax) != stencilMax) { 01115 /* need to apply writemask */ 01116 GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH]; 01117 GLint i; 01118 rb->GetRow(ctx, rb, n, x, y, destVals); 01119 for (i = 0; i < n; i++) { 01120 newVals[i] 01121 = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask); 01122 } 01123 rb->PutRow(ctx, rb, n, x, y, newVals, NULL); 01124 } 01125 else { 01126 rb->PutRow(ctx, rb, n, x, y, stencil, NULL); 01127 } 01128 } 01129 01130 01131 01135 void 01136 _swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb ) 01137 { 01138 const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits; 01139 const GLuint mask = ctx->Stencil.WriteMask[0]; 01140 const GLuint invMask = ~mask; 01141 const GLuint clearVal = (ctx->Stencil.Clear & mask); 01142 const GLuint stencilMax = (1 << stencilBits) - 1; 01143 GLint x, y, width, height; 01144 01145 if (!rb || mask == 0) 01146 return; 01147 01148 ASSERT(rb->DataType == GL_UNSIGNED_BYTE || 01149 rb->DataType == GL_UNSIGNED_SHORT); 01150 01151 ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX); 01152 01153 /* compute region to clear */ 01154 x = ctx->DrawBuffer->_Xmin; 01155 y = ctx->DrawBuffer->_Ymin; 01156 width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; 01157 height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; 01158 01159 if (rb->GetPointer(ctx, rb, 0, 0)) { 01160 /* Direct buffer access */ 01161 if ((mask & stencilMax) != stencilMax) { 01162 /* need to mask the clear */ 01163 if (rb->DataType == GL_UNSIGNED_BYTE) { 01164 GLint i, j; 01165 for (i = 0; i < height; i++) { 01166 GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i); 01167 for (j = 0; j < width; j++) { 01168 stencil[j] = (stencil[j] & invMask) | clearVal; 01169 } 01170 } 01171 } 01172 else { 01173 GLint i, j; 01174 for (i = 0; i < height; i++) { 01175 GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i); 01176 for (j = 0; j < width; j++) { 01177 stencil[j] = (stencil[j] & invMask) | clearVal; 01178 } 01179 } 01180 } 01181 } 01182 else { 01183 /* no bit masking */ 01184 if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) { 01185 /* optimized case */ 01186 /* Note: bottom-to-top raster assumed! */ 01187 GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y); 01188 GLuint len = width * height * sizeof(GLubyte); 01189 _mesa_memset(stencil, clearVal, len); 01190 } 01191 else { 01192 /* general case */ 01193 GLint i; 01194 for (i = 0; i < height; i++) { 01195 GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i); 01196 if (rb->DataType == GL_UNSIGNED_BYTE) { 01197 _mesa_memset(stencil, clearVal, width); 01198 } 01199 else { 01200 _mesa_memset16((short unsigned int*) stencil, clearVal, width); 01201 } 01202 } 01203 } 01204 } 01205 } 01206 else { 01207 /* no direct access */ 01208 if ((mask & stencilMax) != stencilMax) { 01209 /* need to mask the clear */ 01210 if (rb->DataType == GL_UNSIGNED_BYTE) { 01211 GLint i, j; 01212 for (i = 0; i < height; i++) { 01213 GLubyte stencil[MAX_WIDTH]; 01214 rb->GetRow(ctx, rb, width, x, y + i, stencil); 01215 for (j = 0; j < width; j++) { 01216 stencil[j] = (stencil[j] & invMask) | clearVal; 01217 } 01218 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL); 01219 } 01220 } 01221 else { 01222 GLint i, j; 01223 for (i = 0; i < height; i++) { 01224 GLushort stencil[MAX_WIDTH]; 01225 rb->GetRow(ctx, rb, width, x, y + i, stencil); 01226 for (j = 0; j < width; j++) { 01227 stencil[j] = (stencil[j] & invMask) | clearVal; 01228 } 01229 rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL); 01230 } 01231 } 01232 } 01233 else { 01234 /* no bit masking */ 01235 const GLubyte clear8 = (GLubyte) clearVal; 01236 const GLushort clear16 = (GLushort) clearVal; 01237 const void *clear; 01238 GLint i; 01239 if (rb->DataType == GL_UNSIGNED_BYTE) { 01240 clear = &clear8; 01241 } 01242 else { 01243 clear = &clear16; 01244 } 01245 for (i = 0; i < height; i++) { 01246 rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL); 01247 } 01248 } 01249 } 01250 } Generated on Sat May 26 2012 04:19:33 for ReactOS by
1.7.6.1
|