ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

s_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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.