Ignore:
Timestamp:
May 23, 2000, 10:41:28 PM (25 years ago)
Author:
jeroen
Message:

* empty log message *

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/opengl/mesa/stencil.c

    r2962 r3598  
    1 /* $Id: stencil.c,v 1.2 2000-03-01 18:49:35 jeroen Exp $ */
     1/* $Id: stencil.c,v 1.3 2000-05-23 20:40:54 jeroen Exp $ */
    22
    33/*
    44 * Mesa 3-D graphics library
    5  * Version:  3.1
     5 * Version:  3.3
    66 *
    77 * Copyright (C) 1999  Brian Paul   All Rights Reserved.
     
    3131#include "all.h"
    3232#else
    33 #ifndef XFree86Server
    34 #include <stdlib.h>
    35 #include <string.h>
    36 #else
    37 #include "GL/xf86glx.h"
    38 #endif
     33#include "glheader.h"
    3934#include "types.h"
    4035#include "context.h"
     
    4338#include "stencil.h"
    4439#include "enable.h"
     40#include "mem.h"
     41#include "depth.h"
    4542#endif
    4643
    4744
    4845
    49 /*
    50  * Return the address of a stencil buffer value given the window coords:
    51  */
    52 #define STENCIL_ADDRESS(X,Y)  (ctx->Buffer->Stencil + ctx->Buffer->Width * (Y) + (X))
    53 
    54 
    55 void gl_ClearStencil( GLcontext *ctx, GLint s )
    56 {
     46void
     47_mesa_ClearStencil( GLint s )
     48{
     49   GET_CURRENT_CONTEXT(ctx);
    5750   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glClearStencil");
    5851   ctx->Stencil.Clear = (GLstencil) s;
     
    6558
    6659
    67 void gl_StencilFunc( GLcontext *ctx, GLenum func, GLint ref, GLuint mask )
    68 {
     60void
     61_mesa_StencilFunc( GLenum func, GLint ref, GLuint mask )
     62{
     63   GET_CURRENT_CONTEXT(ctx);
    6964   GLint maxref;
    7065
     
    9893
    9994
    100 void gl_StencilMask( GLcontext *ctx, GLuint mask )
    101 {
     95void
     96_mesa_StencilMask( GLuint mask )
     97{
     98   GET_CURRENT_CONTEXT(ctx);
    10299   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilMask");
    103100   ctx->Stencil.WriteMask = (GLstencil) mask;
     
    110107
    111108
    112 void gl_StencilOp( GLcontext *ctx, GLenum fail, GLenum zfail, GLenum zpass )
    113 {
     109void
     110_mesa_StencilOp( GLenum fail, GLenum zfail, GLenum zpass )
     111{
     112   GET_CURRENT_CONTEXT(ctx);
    114113   ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx, "glStencilOp");
    115114   switch (fail) {
     
    185184
    186185/*
     186 * Return the address of a stencil buffer value given the window coords:
     187 */
     188#define STENCIL_ADDRESS(X,Y)  \
     189       (ctx->DrawBuffer->Stencil + ctx->DrawBuffer->Width * (Y) + (X))
     190
     191
     192
     193/*
    187194 * Apply the given stencil operator to the array of stencil values.
    188195 * Don't touch stencil[i] if mask[i] is zero.
    189  * Input:  n - number of pixels in the span
     196 * Input:  n - size of stencil array
    190197 *         oper - the stencil buffer operator
    191198 *         stencil - array of stencil values
    192199 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
     200 * Output:  stencil - modified values
    193201 */
    194 static void apply_stencil_op( GLcontext *ctx, GLenum oper,
    195                               GLuint n, GLstencil stencil[], GLubyte mask[] )
     202static void apply_stencil_op( const GLcontext *ctx, GLenum oper,
     203                              GLuint n, GLstencil stencil[],
     204                              const GLubyte mask[] )
    196205{
    197206   const GLstencil ref = ctx->Stencil.Ref;
     
    205214         break;
    206215      case GL_ZERO:
    207         if (invmask==0) {
    208             for (i=0;i<n;i++) {
    209                if (mask[i]) {
    210                   stencil[i] = 0;
    211                }
    212             }
    213         }
    214         else {
    215             for (i=0;i<n;i++) {
    216                if (mask[i]) {
    217                   stencil[i] = (GLstencil) (stencil[i] & invmask);
    218                }
    219             }
    220         }
    221         break;
     216        if (invmask==0) {
     217            for (i=0;i<n;i++) {
     218               if (mask[i]) {
     219                  stencil[i] = 0;
     220               }
     221            }
     222        }
     223        else {
     224            for (i=0;i<n;i++) {
     225               if (mask[i]) {
     226                  stencil[i] = (GLstencil) (stencil[i] & invmask);
     227               }
     228            }
     229        }
     230        break;
    222231      case GL_REPLACE:
    223         if (invmask==0) {
    224             for (i=0;i<n;i++) {
    225                if (mask[i]) {
     232        if (invmask==0) {
     233            for (i=0;i<n;i++) {
     234               if (mask[i]) {
    226235                  stencil[i] = ref;
    227                }
    228             }
    229         }
    230         else {
    231             for (i=0;i<n;i++) {
    232                if (mask[i]) {
    233                   GLstencil s = stencil[i];
    234                   stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
    235                }
    236             }
    237         }
    238         break;
     236               }
     237            }
     238        }
     239        else {
     240            for (i=0;i<n;i++) {
     241               if (mask[i]) {
     242                  GLstencil s = stencil[i];
     243                  stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));
     244               }
     245            }
     246        }
     247        break;
    239248      case GL_INCR:
    240         if (invmask==0) {
    241             for (i=0;i<n;i++) {
    242                if (mask[i]) {
    243                   GLstencil s = stencil[i];
    244                   if (s < STENCIL_MAX) {
    245                      stencil[i] = (GLstencil) (s+1);
    246                   }
    247                }
    248             }
    249         }
    250         else {
    251             for (i=0;i<n;i++) {
    252                if (mask[i]) {
    253                   /* VERIFY logic of adding 1 to a write-masked value */
    254                   GLstencil s = stencil[i];
    255                   if (s < STENCIL_MAX) {
    256                      stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
    257                   }
    258                }
    259             }
    260         }
    261         break;
     249        if (invmask==0) {
     250            for (i=0;i<n;i++) {
     251               if (mask[i]) {
     252                  GLstencil s = stencil[i];
     253                  if (s < STENCIL_MAX) {
     254                     stencil[i] = (GLstencil) (s+1);
     255                  }
     256               }
     257            }
     258        }
     259        else {
     260            for (i=0;i<n;i++) {
     261               if (mask[i]) {
     262                  /* VERIFY logic of adding 1 to a write-masked value */
     263                  GLstencil s = stencil[i];
     264                  if (s < STENCIL_MAX) {
     265                     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
     266                  }
     267               }
     268            }
     269        }
     270        break;
    262271      case GL_DECR:
    263         if (invmask==0) {
    264             for (i=0;i<n;i++) {
    265                if (mask[i]) {
    266                   GLstencil s = stencil[i];
    267                   if (s>0) {
    268                      stencil[i] = (GLstencil) (s-1);
    269                   }
    270                }
    271             }
    272         }
    273         else {
    274             for (i=0;i<n;i++) {
    275                if (mask[i]) {
    276                   /* VERIFY logic of subtracting 1 to a write-masked value */
    277                   GLstencil s = stencil[i];
    278                   if (s>0) {
    279                      stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
    280                   }
    281                }
    282             }
    283         }
    284         break;
     272        if (invmask==0) {
     273            for (i=0;i<n;i++) {
     274               if (mask[i]) {
     275                  GLstencil s = stencil[i];
     276                  if (s>0) {
     277                     stencil[i] = (GLstencil) (s-1);
     278                  }
     279               }
     280            }
     281        }
     282        else {
     283            for (i=0;i<n;i++) {
     284               if (mask[i]) {
     285                  /* VERIFY logic of subtracting 1 to a write-masked value */
     286                  GLstencil s = stencil[i];
     287                  if (s>0) {
     288                     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
     289                  }
     290               }
     291            }
     292        }
     293        break;
    285294      case GL_INCR_WRAP_EXT:
    286         if (invmask==0) {
    287             for (i=0;i<n;i++) {
    288                if (mask[i]) {
     295        if (invmask==0) {
     296            for (i=0;i<n;i++) {
     297               if (mask[i]) {
    289298                  stencil[i]++;
    290                }
    291             }
    292         }
    293         else {
    294             for (i=0;i<n;i++) {
    295                if (mask[i]) {
     299               }
     300            }
     301        }
     302        else {
     303            for (i=0;i<n;i++) {
     304               if (mask[i]) {
    296305                  GLstencil s = stencil[i];
    297                   stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (stencil[i]+1)));
    298                }
    299             }
    300         }
    301         break;
     306                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));
     307               }
     308            }
     309        }
     310        break;
    302311      case GL_DECR_WRAP_EXT:
    303         if (invmask==0) {
    304             for (i=0;i<n;i++) {
    305                if (mask[i]) {
    306                   stencil[i]--;
    307                }
    308             }
    309         }
    310         else {
    311             for (i=0;i<n;i++) {
    312                if (mask[i]) {
     312        if (invmask==0) {
     313            for (i=0;i<n;i++) {
     314               if (mask[i]) {
     315                  stencil[i]--;
     316               }
     317            }
     318        }
     319        else {
     320            for (i=0;i<n;i++) {
     321               if (mask[i]) {
    313322                  GLstencil s = stencil[i];
    314                   stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (stencil[i]-1)));
    315                }
    316             }
    317         }
    318         break;
     323                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));
     324               }
     325            }
     326        }
     327        break;
    319328      case GL_INVERT:
    320         if (invmask==0) {
    321             for (i=0;i<n;i++) {
    322                if (mask[i]) {
    323                   GLstencil s = stencil[i];
    324                   stencil[i] = (GLstencil) ~s;
    325                }
    326             }
    327         }
    328         else {
    329             for (i=0;i<n;i++) {
    330                if (mask[i]) {
    331                   GLstencil s = stencil[i];
    332                   stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
    333                }
    334             }
    335         }
    336         break;
     329        if (invmask==0) {
     330            for (i=0;i<n;i++) {
     331               if (mask[i]) {
     332                  GLstencil s = stencil[i];
     333                  stencil[i] = (GLstencil) ~s;
     334               }
     335            }
     336        }
     337        else {
     338            for (i=0;i<n;i++) {
     339               if (mask[i]) {
     340                  GLstencil s = stencil[i];
     341                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));
     342               }
     343            }
     344        }
     345        break;
    337346      default:
    338347         gl_problem(ctx, "Bad stencil op in apply_stencil_op");
     
    342351
    343352
    344 
    345353/*
    346  * Apply stencil test to a span of pixels before depth buffering.
    347  * Input:  n - number of pixels in the span
    348  *         x, y - coordinate of left-most pixel in the span
     354 * Apply stencil test to an array of stencil values (before depth buffering).
     355 * Input:  n - number of pixels in the array
     356 *         stencil - array of [n] stencil values
    349357 *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel
    350358 * Output:  mask - pixels which fail the stencil test will have their
    351359 *                 mask flag set to 0.
    352  * Return:  0 = all pixels failed, 1 = zero or more pixels passed.
     360 *          stencil - updated stencil values (where the test passed)
     361 * Return:  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed.
    353362 */
    354 GLint gl_stencil_span( GLcontext *ctx,
    355                        GLuint n, GLint x, GLint y, GLubyte mask[] )
    356 {
    357    GLubyte fail[MAX_WIDTH];
    358    GLint allfail = 0;
     363static GLboolean
     364do_stencil_test( GLcontext *ctx, GLuint n, GLstencil stencil[],
     365                 GLubyte mask[] )
     366{
     367   GLubyte fail[PB_SIZE];
     368   GLboolean allfail = GL_FALSE;
    359369   GLuint i;
    360370   GLstencil r, s;
    361    GLstencil *stencil;
    362 
    363    stencil = STENCIL_ADDRESS( x, y );
     371
     372   ASSERT(n <= PB_SIZE);
    364373
    365374   /*
     
    376385         /* always fail */
    377386         for (i=0;i<n;i++) {
    378             if (mask[i]) {
    379                mask[i] = 0;
    380                fail[i] = 1;
    381             }
    382             else {
    383                fail[i] = 0;
    384             }
    385         }
    386          allfail = 1;
    387         break;
     387            if (mask[i]) {
     388               mask[i] = 0;
     389               fail[i] = 1;
     390            }
     391            else {
     392               fail[i] = 0;
     393            }
     394        }
     395         allfail = GL_TRUE;
     396        break;
    388397      case GL_LESS:
    389         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    390         for (i=0;i<n;i++) {
    391             if (mask[i]) {
    392                s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
    393                if (r < s) {
    394                   /* passed */
    395                   fail[i] = 0;
    396                }
    397                else {
    398                   fail[i] = 1;
    399                   mask[i] = 0;
    400                }
    401             }
    402             else {
    403                fail[i] = 0;
    404             }
    405         }
    406         break;
     398        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     399        for (i=0;i<n;i++) {
     400            if (mask[i]) {
     401               s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
     402               if (r < s) {
     403                  /* passed */
     404                  fail[i] = 0;
     405               }
     406               else {
     407                  fail[i] = 1;
     408                  mask[i] = 0;
     409               }
     410            }
     411            else {
     412               fail[i] = 0;
     413            }
     414        }
     415        break;
    407416      case GL_LEQUAL:
    408         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    409         for (i=0;i<n;i++) {
    410             if (mask[i]) {
    411                s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
    412                if (r <= s) {
    413                   /* pass */
    414                   fail[i] = 0;
    415                }
    416                else {
    417                   fail[i] = 1;
    418                   mask[i] = 0;
    419                }
    420             }
    421             else {
    422                fail[i] = 0;
    423             }
    424         }
    425         break;
     417        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     418        for (i=0;i<n;i++) {
     419            if (mask[i]) {
     420               s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
     421               if (r <= s) {
     422                  /* pass */
     423                  fail[i] = 0;
     424               }
     425               else {
     426                  fail[i] = 1;
     427                  mask[i] = 0;
     428               }
     429            }
     430            else {
     431               fail[i] = 0;
     432            }
     433        }
     434        break;
    426435      case GL_GREATER:
    427         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    428         for (i=0;i<n;i++) {
    429             if (mask[i]) {
    430                s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
    431                if (r > s) {
    432                   /* passed */
    433                   fail[i] = 0;
    434                }
    435                else {
    436                   fail[i] = 1;
    437                   mask[i] = 0;
    438                }
    439             }
    440             else {
    441                fail[i] = 0;
    442             }
    443         }
    444         break;
     436        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     437        for (i=0;i<n;i++) {
     438            if (mask[i]) {
     439               s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
     440               if (r > s) {
     441                  /* passed */
     442                  fail[i] = 0;
     443               }
     444               else {
     445                  fail[i] = 1;
     446                  mask[i] = 0;
     447               }
     448            }
     449            else {
     450               fail[i] = 0;
     451            }
     452        }
     453        break;
    445454      case GL_GEQUAL:
    446         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    447         for (i=0;i<n;i++) {
    448             if (mask[i]) {
    449                s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
    450                if (r >= s) {
    451                   /* passed */
    452                   fail[i] = 0;
    453                }
    454                else {
    455                   fail[i] = 1;
    456                   mask[i] = 0;
    457                }
    458             }
    459             else {
    460                fail[i] = 0;
    461             }
    462         }
    463         break;
     455        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     456        for (i=0;i<n;i++) {
     457            if (mask[i]) {
     458               s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
     459               if (r >= s) {
     460                  /* passed */
     461                  fail[i] = 0;
     462               }
     463               else {
     464                  fail[i] = 1;
     465                  mask[i] = 0;
     466               }
     467            }
     468            else {
     469               fail[i] = 0;
     470            }
     471        }
     472        break;
    464473      case GL_EQUAL:
    465         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    466         for (i=0;i<n;i++) {
    467             if (mask[i]) {
    468                s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
    469                if (r == s) {
    470                   /* passed */
    471                   fail[i] = 0;
    472                }
    473                else {
    474                   fail[i] = 1;
    475                   mask[i] = 0;
    476                }
    477             }
    478             else {
    479                fail[i] = 0;
    480             }
    481         }
    482         break;
     474        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     475        for (i=0;i<n;i++) {
     476            if (mask[i]) {
     477               s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
     478               if (r == s) {
     479                  /* passed */
     480                  fail[i] = 0;
     481               }
     482               else {
     483                  fail[i] = 1;
     484                  mask[i] = 0;
     485               }
     486            }
     487            else {
     488               fail[i] = 0;
     489            }
     490        }
     491        break;
    483492      case GL_NOTEQUAL:
    484         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    485         for (i=0;i<n;i++) {
    486             if (mask[i]) {
    487                s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
    488                if (r != s) {
    489                   /* passed */
    490                   fail[i] = 0;
    491                }
    492                else {
    493                   fail[i] = 1;
    494                   mask[i] = 0;
    495                }
    496             }
    497             else {
    498                fail[i] = 0;
    499             }
    500         }
    501         break;
     493        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     494        for (i=0;i<n;i++) {
     495            if (mask[i]) {
     496               s = (GLstencil) (stencil[i] & ctx->Stencil.ValueMask);
     497               if (r != s) {
     498                  /* passed */
     499                  fail[i] = 0;
     500               }
     501               else {
     502                  fail[i] = 1;
     503                  mask[i] = 0;
     504               }
     505            }
     506            else {
     507               fail[i] = 0;
     508            }
     509        }
     510        break;
    502511      case GL_ALWAYS:
    503         /* always pass */
    504         for (i=0;i<n;i++) {
    505             fail[i] = 0;
    506         }
    507         break;
     512        /* always pass */
     513        for (i=0;i<n;i++) {
     514            fail[i] = 0;
     515        }
     516        break;
    508517      default:
    509518         gl_problem(ctx, "Bad stencil func in gl_stencil_span");
     
    515524   }
    516525
    517    return (allfail) ? 0 : 1;
     526   return !allfail;
    518527}
    519528
     
    522531
    523532/*
    524  * Apply the combination depth-buffer/stencil operator to a span of pixels.
     533 * Apply stencil and depth testing to an array of pixels.
     534 * Hardware or software stencil buffer acceptable.
    525535 * Input:  n - number of pixels in the span
    526  *         x, y - location of leftmost pixel in span
    527536 *         z - array [n] of z values
    528  * Input:  mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
    529  * Output:  mask - array [n] of flags (1=depth test passed, 0=failed)
     537 *         stencil - array [n] of stencil values
     538 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
     539 * Output:  stencil - modified stencil values
     540 *          mask - array [n] of flags (1=stencil and depth test passed)
     541 * Return: GL_TRUE - all fragments failed the testing
     542 *         GL_FALSE - one or more fragments passed the testing
     543 *
    530544 */
    531 void gl_depth_stencil_span( GLcontext *ctx,
    532                             GLuint n, GLint x, GLint y, const GLdepth z[],
    533                             GLubyte mask[] )
    534 {
    535    GLstencil *stencil = STENCIL_ADDRESS(x, y);
    536 
     545static GLboolean
     546stencil_and_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
     547                             const GLdepth z[], GLstencil stencil[],
     548                             GLubyte mask[] )
     549{
     550   ASSERT(ctx->Stencil.Enabled);
     551   ASSERT(n <= PB_SIZE);
     552
     553   /*
     554    * Apply the stencil test to the fragments.
     555    * failMask[i] is 1 if the stencil test failed.
     556    */
     557   if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) {
     558      /* all fragments failed the stencil test, we're done. */
     559      return GL_FALSE;
     560   }
     561
     562
     563   /*
     564    * Some fragments passed the stencil test, apply depth test to them
     565    * and apply Zpass and Zfail stencil ops.
     566    */
    537567   if (ctx->Depth.Test==GL_FALSE) {
    538568      /*
     
    552582
    553583      /* apply the depth test */
    554       if (ctx->Driver.DepthTestSpan)
    555          (*ctx->Driver.DepthTestSpan)( ctx, n, x, y, z, mask );
     584      _mesa_depth_test_span(ctx, n, x, y, z, mask);
    556585
    557586      /* Set the stencil pass/fail flags according to result of depth testing.
     
    561590       *    Depth test passed
    562591       * else
    563        *    assert(oldmask[i] && !newmask[i])
     592       *    ASSERT(oldmask[i] && !newmask[i])
    564593       *    Depth test failed
    565594       * endif
     
    579608      }
    580609   }
     610
     611   return GL_TRUE;  /* one or more fragments passed both tests */
     612}
     613
     614
     615
     616/*
     617 * Apply stencil and depth testing to the span of pixels.
     618 * Both software and hardware stencil buffers are acceptable.
     619 * Input:  n - number of pixels in the span
     620 *         x, y - location of leftmost pixel in span
     621 *         z - array [n] of z values
     622 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
     623 * Output:  mask - array [n] of flags (1=stencil and depth test passed)
     624 * Return: GL_TRUE - all fragments failed the testing
     625 *         GL_FALSE - one or more fragments passed the testing
     626 *
     627 */
     628GLboolean
     629gl_stencil_and_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
     630                                const GLdepth z[], GLubyte mask[] )
     631{
     632   GLstencil stencilRow[MAX_WIDTH];
     633   GLstencil *stencil;
     634   GLboolean result;
     635
     636   ASSERT(ctx->Stencil.Enabled);
     637   ASSERT(n <= MAX_WIDTH);
     638
     639   /* Get initial stencil values */
     640   if (ctx->Driver.WriteStencilSpan) {
     641      ASSERT(ctx->Driver.ReadStencilSpan);
     642      /* Get stencil values from the hardware stencil buffer */
     643      (*ctx->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
     644      stencil = stencilRow;
     645   }
     646   else {
     647      /* software stencil buffer */
     648      stencil = STENCIL_ADDRESS(x, y);
     649   }
     650
     651   /* do all the stencil/depth testing/updating */
     652   result = stencil_and_depth_test_span( ctx, n, x, y, z, stencil, mask );
     653
     654   if (ctx->Driver.WriteStencilSpan) {
     655      /* Write updated stencil values into hardware stencil buffer */
     656      (ctx->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
     657   }
     658
     659   return result;
    581660}
    582661
     
    586665/*
    587666 * Apply the given stencil operator for each pixel in the array whose
    588  * mask flag is set.
     667 * mask flag is set.  This is for software stencil buffers only.
    589668 * Input:  n - number of pixels in the span
    590669 *         x, y - array of [n] pixels
     
    592671 *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator
    593672 */
    594 static void apply_stencil_op_to_pixels( GLcontext *ctx,
    595                                         GLuint n, const GLint x[],
    596                                         const GLint y[],
    597                                         GLenum oper, GLubyte mask[] )
    598 {
     673static void
     674apply_stencil_op_to_pixels( const GLcontext *ctx,
     675                            GLuint n, const GLint x[], const GLint y[],
     676                            GLenum oper, const GLubyte mask[] )
     677{
     678   const GLstencil ref = ctx->Stencil.Ref;
     679   const GLstencil wrtmask = ctx->Stencil.WriteMask;
     680   const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask);
    599681   GLuint i;
    600    GLstencil ref;
    601    GLstencil wrtmask, invmask;
    602 
    603    wrtmask = ctx->Stencil.WriteMask;
    604    invmask = (GLstencil) (~ctx->Stencil.WriteMask);
    605 
    606    ref = ctx->Stencil.Ref;
     682
     683   ASSERT(!ctx->Driver.WriteStencilSpan);  /* software stencil buffer only! */
    607684
    608685   switch (oper) {
     
    611688         break;
    612689      case GL_ZERO:
    613         if (invmask==0) {
    614             for (i=0;i<n;i++) {
    615                if (mask[i]) {
     690        if (invmask==0) {
     691            for (i=0;i<n;i++) {
     692               if (mask[i]) {
    616693                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    617694                  *sptr = 0;
    618                }
    619             }
    620         }
    621         else {
    622             for (i=0;i<n;i++) {
    623                if (mask[i]) {
     695               }
     696            }
     697        }
     698        else {
     699            for (i=0;i<n;i++) {
     700               if (mask[i]) {
    624701                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    625                   *sptr = (GLstencil) (invmask & *sptr);
    626                }
    627             }
    628         }
    629         break;
     702                  *sptr = (GLstencil) (invmask & *sptr);
     703               }
     704            }
     705        }
     706        break;
    630707      case GL_REPLACE:
    631         if (invmask==0) {
    632             for (i=0;i<n;i++) {
    633                if (mask[i]) {
     708        if (invmask==0) {
     709            for (i=0;i<n;i++) {
     710               if (mask[i]) {
    634711                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    635712                  *sptr = ref;
    636                }
    637             }
    638         }
    639         else {
    640             for (i=0;i<n;i++) {
    641                if (mask[i]) {
     713               }
     714            }
     715        }
     716        else {
     717            for (i=0;i<n;i++) {
     718               if (mask[i]) {
    642719                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    643                   *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
    644                }
    645             }
    646         }
    647         break;
     720                  *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));
     721               }
     722            }
     723        }
     724        break;
    648725      case GL_INCR:
    649         if (invmask==0) {
    650             for (i=0;i<n;i++) {
    651                if (mask[i]) {
     726        if (invmask==0) {
     727            for (i=0;i<n;i++) {
     728               if (mask[i]) {
    652729                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    653                   if (*sptr < STENCIL_MAX) {
    654                      *sptr = (GLstencil) (*sptr + 1);
    655                   }
    656                }
    657             }
    658         }
    659         else {
    660             for (i=0;i<n;i++) {
    661                if (mask[i]) {
     730                  if (*sptr < STENCIL_MAX) {
     731                     *sptr = (GLstencil) (*sptr + 1);
     732                  }
     733               }
     734            }
     735        }
     736        else {
     737            for (i=0;i<n;i++) {
     738               if (mask[i]) {
    662739                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    663                   if (*sptr < STENCIL_MAX) {
    664                      *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
    665                   }
    666                }
    667             }
    668         }
    669         break;
     740                  if (*sptr < STENCIL_MAX) {
     741                     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
     742                  }
     743               }
     744            }
     745        }
     746        break;
    670747      case GL_DECR:
    671         if (invmask==0) {
    672             for (i=0;i<n;i++) {
    673                if (mask[i]) {
     748        if (invmask==0) {
     749            for (i=0;i<n;i++) {
     750               if (mask[i]) {
    674751                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    675                   if (*sptr>0) {
    676                      *sptr = (GLstencil) (*sptr - 1);
    677                   }
    678                }
    679             }
    680         }
    681         else {
    682             for (i=0;i<n;i++) {
    683                if (mask[i]) {
     752                  if (*sptr>0) {
     753                     *sptr = (GLstencil) (*sptr - 1);
     754                  }
     755               }
     756            }
     757        }
     758        else {
     759            for (i=0;i<n;i++) {
     760               if (mask[i]) {
    684761                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    685                   if (*sptr>0) {
    686                      *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
    687                   }
    688                }
    689             }
    690         }
    691         break;
     762                  if (*sptr>0) {
     763                     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
     764                  }
     765               }
     766            }
     767        }
     768        break;
    692769      case GL_INCR_WRAP_EXT:
    693         if (invmask==0) {
    694             for (i=0;i<n;i++) {
    695                if (mask[i]) {
     770        if (invmask==0) {
     771            for (i=0;i<n;i++) {
     772               if (mask[i]) {
    696773                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    697774                  *sptr = (GLstencil) (*sptr + 1);
    698                }
    699             }
    700         }
    701         else {
    702             for (i=0;i<n;i++) {
    703                if (mask[i]) {
     775               }
     776            }
     777        }
     778        else {
     779            for (i=0;i<n;i++) {
     780               if (mask[i]) {
    704781                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    705782                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));
    706                }
    707             }
    708         }
    709         break;
     783               }
     784            }
     785        }
     786        break;
    710787      case GL_DECR_WRAP_EXT:
    711         if (invmask==0) {
    712             for (i=0;i<n;i++) {
    713                if (mask[i]) {
     788        if (invmask==0) {
     789            for (i=0;i<n;i++) {
     790               if (mask[i]) {
    714791                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    715792                  *sptr = (GLstencil) (*sptr - 1);
    716                }
    717             }
    718         }
    719         else {
    720             for (i=0;i<n;i++) {
    721                if (mask[i]) {
     793               }
     794            }
     795        }
     796        else {
     797            for (i=0;i<n;i++) {
     798               if (mask[i]) {
    722799                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    723800                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));
    724                }
    725             }
    726         }
    727         break;
     801               }
     802            }
     803        }
     804        break;
    728805      case GL_INVERT:
    729         if (invmask==0) {
    730             for (i=0;i<n;i++) {
    731                if (mask[i]) {
     806        if (invmask==0) {
     807            for (i=0;i<n;i++) {
     808               if (mask[i]) {
    732809                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    733810                  *sptr = (GLstencil) (~*sptr);
    734                }
    735             }
    736         }
    737         else {
    738             for (i=0;i<n;i++) {
    739                if (mask[i]) {
     811               }
     812            }
     813        }
     814        else {
     815            for (i=0;i<n;i++) {
     816               if (mask[i]) {
    740817                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );
    741818                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));
    742                }
    743             }
    744         }
    745         break;
     819               }
     820            }
     821        }
     822        break;
    746823      default:
    747824         gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
     
    753830/*
    754831 * Apply stencil test to an array of pixels before depth buffering.
     832 * Used for software stencil buffer only.
    755833 * Input:  n - number of pixels in the span
    756834 *         x, y - array of [n] pixels to stencil
     
    760838 * Return:  0 = all pixels failed, 1 = zero or more pixels passed.
    761839 */
    762 GLint gl_stencil_pixels( GLcontext *ctx,
    763                          GLuint n, const GLint x[], const GLint y[],
    764                         GLubyte mask[] )
     840static GLboolean
     841stencil_test_pixels( GLcontext *ctx, GLuint n,
     842                     const GLint x[], const GLint y[], GLubyte mask[] )
    765843{
    766844   GLubyte fail[PB_SIZE];
    767845   GLstencil r, s;
    768846   GLuint i;
    769    GLint allfail = 0;
     847   GLboolean allfail = GL_FALSE;
     848
     849   ASSERT(!ctx->Driver.WriteStencilSpan);  /* software stencil buffer only! */
    770850
    771851   /*
     
    783863         /* always fail */
    784864         for (i=0;i<n;i++) {
    785             if (mask[i]) {
    786                mask[i] = 0;
    787                fail[i] = 1;
    788             }
    789             else {
    790                fail[i] = 0;
    791             }
    792         }
    793          allfail = 1;
    794         break;
     865            if (mask[i]) {
     866               mask[i] = 0;
     867               fail[i] = 1;
     868            }
     869            else {
     870               fail[i] = 0;
     871            }
     872        }
     873         allfail = GL_TRUE;
     874        break;
    795875      case GL_LESS:
    796         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    797         for (i=0;i<n;i++) {
    798             if (mask[i]) {
     876        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     877        for (i=0;i<n;i++) {
     878            if (mask[i]) {
    799879               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
    800                s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
    801                if (r < s) {
    802                   /* passed */
    803                   fail[i] = 0;
    804                }
    805                else {
    806                   fail[i] = 1;
    807                   mask[i] = 0;
    808                }
    809             }
    810             else {
    811                fail[i] = 0;
    812             }
    813         }
    814         break;
     880               s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
     881               if (r < s) {
     882                  /* passed */
     883                  fail[i] = 0;
     884               }
     885               else {
     886                  fail[i] = 1;
     887                  mask[i] = 0;
     888               }
     889            }
     890            else {
     891               fail[i] = 0;
     892            }
     893        }
     894        break;
    815895      case GL_LEQUAL:
    816         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    817         for (i=0;i<n;i++) {
    818             if (mask[i]) {
     896        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     897        for (i=0;i<n;i++) {
     898            if (mask[i]) {
    819899               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
    820                s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
    821                if (r <= s) {
    822                   /* pass */
    823                   fail[i] = 0;
    824                }
    825                else {
    826                   fail[i] = 1;
    827                   mask[i] = 0;
    828                }
    829             }
    830             else {
    831                fail[i] = 0;
    832             }
    833         }
    834         break;
     900               s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
     901               if (r <= s) {
     902                  /* pass */
     903                  fail[i] = 0;
     904               }
     905               else {
     906                  fail[i] = 1;
     907                  mask[i] = 0;
     908               }
     909            }
     910            else {
     911               fail[i] = 0;
     912            }
     913        }
     914        break;
    835915      case GL_GREATER:
    836         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    837         for (i=0;i<n;i++) {
    838             if (mask[i]) {
     916        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     917        for (i=0;i<n;i++) {
     918            if (mask[i]) {
    839919               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
    840                s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
    841                if (r > s) {
    842                   /* passed */
    843                   fail[i] = 0;
    844                }
    845                else {
    846                   fail[i] = 1;
    847                   mask[i] = 0;
    848                }
    849             }
    850             else {
    851                fail[i] = 0;
    852             }
    853         }
    854         break;
     920               s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
     921               if (r > s) {
     922                  /* passed */
     923                  fail[i] = 0;
     924               }
     925               else {
     926                  fail[i] = 1;
     927                  mask[i] = 0;
     928               }
     929            }
     930            else {
     931               fail[i] = 0;
     932            }
     933        }
     934        break;
    855935      case GL_GEQUAL:
    856         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    857         for (i=0;i<n;i++) {
    858             if (mask[i]) {
     936        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     937        for (i=0;i<n;i++) {
     938            if (mask[i]) {
    859939               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
    860                s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
    861                if (r >= s) {
    862                   /* passed */
    863                   fail[i] = 0;
    864                }
    865                else {
    866                   fail[i] = 1;
    867                   mask[i] = 0;
    868                }
    869             }
    870             else {
    871                fail[i] = 0;
    872             }
    873         }
    874         break;
     940               s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
     941               if (r >= s) {
     942                  /* passed */
     943                  fail[i] = 0;
     944               }
     945               else {
     946                  fail[i] = 1;
     947                  mask[i] = 0;
     948               }
     949            }
     950            else {
     951               fail[i] = 0;
     952            }
     953        }
     954        break;
    875955      case GL_EQUAL:
    876         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    877         for (i=0;i<n;i++) {
    878             if (mask[i]) {
     956        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     957        for (i=0;i<n;i++) {
     958            if (mask[i]) {
    879959               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
    880                s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
    881                if (r == s) {
    882                   /* passed */
    883                   fail[i] = 0;
    884                }
    885                else {
    886                   fail[i] = 1;
    887                   mask[i] = 0;
    888                }
    889             }
    890             else {
    891                fail[i] = 0;
    892             }
    893         }
    894         break;
     960               s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
     961               if (r == s) {
     962                  /* passed */
     963                  fail[i] = 0;
     964               }
     965               else {
     966                  fail[i] = 1;
     967                  mask[i] = 0;
     968               }
     969            }
     970            else {
     971               fail[i] = 0;
     972            }
     973        }
     974        break;
    895975      case GL_NOTEQUAL:
    896         r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
    897         for (i=0;i<n;i++) {
    898             if (mask[i]) {
     976        r = (GLstencil) (ctx->Stencil.Ref & ctx->Stencil.ValueMask);
     977        for (i=0;i<n;i++) {
     978            if (mask[i]) {
    899979               GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);
    900                s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
    901                if (r != s) {
    902                   /* passed */
    903                   fail[i] = 0;
    904                }
    905                else {
    906                   fail[i] = 1;
    907                   mask[i] = 0;
    908                }
    909             }
    910             else {
    911                fail[i] = 0;
    912             }
    913         }
    914         break;
     980               s = (GLstencil) (*sptr & ctx->Stencil.ValueMask);
     981               if (r != s) {
     982                  /* passed */
     983                  fail[i] = 0;
     984               }
     985               else {
     986                  fail[i] = 1;
     987                  mask[i] = 0;
     988               }
     989            }
     990            else {
     991               fail[i] = 0;
     992            }
     993        }
     994        break;
    915995      case GL_ALWAYS:
    916         /* always pass */
    917         for (i=0;i<n;i++) {
    918             fail[i] = 0;
    919         }
    920         break;
     996        /* always pass */
     997        for (i=0;i<n;i++) {
     998            fail[i] = 0;
     999        }
     1000        break;
    9211001      default:
    9221002         gl_problem(ctx, "Bad stencil func in gl_stencil_pixels");
     
    9241004   }
    9251005
    926    apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
    927 
    928    return (allfail) ? 0 : 1;
     1006   if (ctx->Stencil.FailFunc != GL_KEEP) {
     1007      apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc, fail );
     1008   }
     1009
     1010   return !allfail;
    9291011}
    9301012
     
    9331015
    9341016/*
    935  * Apply the combination depth-buffer/stencil operator to a span of pixels.
    936  * Input:  n - number of pixels in the span
    937  *         x, y - array of [n] pixels to stencil
     1017 * Apply stencil and depth testing to an array of pixels.
     1018 * This is used both for software and hardware stencil buffers.
     1019 *
     1020 * The comments in this function are a bit sparse but the code is
     1021 * almost identical to stencil_and_depth_test_span(), which is well
     1022 * commented.
     1023 *
     1024 * Input:  n - number of pixels in the array
     1025 *         x, y - array of [n] pixel positions
    9381026 *         z - array [n] of z values
    939  * Input:  mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
    940  * Output:  mask - array [n] of flags (1=depth test passed, 0=failed)
     1027 *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel)
     1028 * Output: mask - array [n] of flags (1=stencil and depth test passed)
     1029 * Return: GL_TRUE - all fragments failed the testing
     1030 *         GL_FALSE - one or more fragments passed the testing
    9411031 */
    942 void gl_depth_stencil_pixels( GLcontext *ctx,
    943                               GLuint n, const GLint x[], const GLint y[],
    944                               const GLdepth z[], GLubyte mask[] )
    945 {
    946    if (ctx->Depth.Test==GL_FALSE) {
    947       /*
    948        * No depth buffer, just apply zpass stencil function to active pixels.
    949        */
    950       apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
     1032GLboolean
     1033gl_stencil_and_depth_test_pixels( GLcontext *ctx,
     1034                                  GLuint n, const GLint x[], const GLint y[],
     1035                                  const GLdepth z[], GLubyte mask[] )
     1036{
     1037   ASSERT(ctx->Stencil.Enabled);
     1038   ASSERT(n <= PB_SIZE);
     1039
     1040   if (ctx->Driver.WriteStencilPixels) {
     1041      /*** Hardware stencil buffer ***/
     1042      GLstencil stencil[PB_SIZE];
     1043      GLubyte mask[PB_SIZE];
     1044
     1045      ASSERT(ctx->Driver.ReadStencilPixels);
     1046      (*ctx->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);
     1047
     1048
     1049      if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) {
     1050         /* all fragments failed the stencil test, we're done. */
     1051         return GL_FALSE;
     1052      }
     1053
     1054      if (ctx->Depth.Test == GL_FALSE) {
     1055         apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask );
     1056      }
     1057      else {
     1058         GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
     1059         GLuint i;
     1060
     1061         MEMCPY(oldmask, mask, n * sizeof(GLubyte));
     1062
     1063         _mesa_depth_test_pixels(ctx, n, x, y, z, mask);
     1064
     1065         for (i=0;i<n;i++) {
     1066            ASSERT(mask[i] == 0 || mask[i] == 1);
     1067            passmask[i] = oldmask[i] & mask[i];
     1068            failmask[i] = oldmask[i] & (mask[i] ^ 1);
     1069         }
     1070
     1071         if (ctx->Stencil.ZFailFunc != GL_KEEP) {
     1072            apply_stencil_op( ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask );
     1073         }
     1074         if (ctx->Stencil.ZPassFunc != GL_KEEP) {
     1075            apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask );
     1076         }
     1077      }
     1078
     1079      /* Write updated stencil values into hardware stencil buffer */
     1080      (ctx->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, mask );
     1081
     1082      return GL_TRUE;
     1083
    9511084   }
    9521085   else {
    953       /*
    954        * Perform depth buffering, then apply zpass or zfail stencil function.
    955        */
    956       GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
    957       GLuint i;
    958 
    959       /* save the current mask bits */
    960       MEMCPY(oldmask, mask, n * sizeof(GLubyte));
    961 
    962       /* apply the depth test */
    963       if (ctx->Driver.DepthTestPixels)
    964          (*ctx->Driver.DepthTestPixels)( ctx, n, x, y, z, mask );
    965 
    966       /* Set the stencil pass/fail flags according to result of depth testing.
    967        * if oldmask[i] == 0 then
    968        *    Don't touch the stencil value
    969        * else if oldmask[i] and newmask[i] then
    970        *    Depth test passed
    971        * else
    972        *    assert(oldmask[i] && !newmask[i])
    973        *    Depth test failed
    974        * endif
    975        */
    976       for (i=0;i<n;i++) {
    977          ASSERT(mask[i] == 0 || mask[i] == 1);
    978          passmask[i] = oldmask[i] & mask[i];
    979          failmask[i] = oldmask[i] & (mask[i] ^ 1);
    980       }
    981 
    982       /* apply the pass and fail operations */
    983       apply_stencil_op_to_pixels( ctx, n, x, y,
    984                                   ctx->Stencil.ZFailFunc, failmask );
    985       apply_stencil_op_to_pixels( ctx, n, x, y,
    986                                   ctx->Stencil.ZPassFunc, passmask );
    987    }
    988 
     1086      /*** Software stencil buffer ***/
     1087
     1088      if (stencil_test_pixels(ctx, n, x, y, mask) == GL_FALSE) {
     1089         /* all fragments failed the stencil test, we're done. */
     1090         return GL_FALSE;
     1091      }
     1092
     1093
     1094      if (ctx->Depth.Test==GL_FALSE) {
     1095         apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
     1096      }
     1097      else {
     1098         GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
     1099         GLuint i;
     1100
     1101         MEMCPY(oldmask, mask, n * sizeof(GLubyte));
     1102
     1103         _mesa_depth_test_pixels(ctx, n, x, y, z, mask);
     1104
     1105         for (i=0;i<n;i++) {
     1106            ASSERT(mask[i] == 0 || mask[i] == 1);
     1107            passmask[i] = oldmask[i] & mask[i];
     1108            failmask[i] = oldmask[i] & (mask[i] ^ 1);
     1109         }
     1110
     1111         if (ctx->Stencil.ZFailFunc != GL_KEEP) {
     1112            apply_stencil_op_to_pixels( ctx, n, x, y,
     1113                                        ctx->Stencil.ZFailFunc, failmask );
     1114         }
     1115         if (ctx->Stencil.ZPassFunc != GL_KEEP) {
     1116            apply_stencil_op_to_pixels( ctx, n, x, y,
     1117                                        ctx->Stencil.ZPassFunc, passmask );
     1118         }
     1119      }
     1120
     1121      return GL_TRUE;  /* one or more fragments passed both tests */
     1122   }
    9891123}
    9901124
     
    9931127/*
    9941128 * Return a span of stencil values from the stencil buffer.
     1129 * Used for glRead/CopyPixels
    9951130 * Input:  n - how many pixels
    9961131 *         x,y - location of first pixel
     
    9981133 */
    9991134void gl_read_stencil_span( GLcontext *ctx,
    1000                            GLuint n, GLint x, GLint y, GLstencil stencil[] )
    1001 {
    1002    if (ctx->Buffer->Stencil) {
    1003       const GLstencil *s = STENCIL_ADDRESS( x, y );
     1135                           GLint n, GLint x, GLint y, GLstencil stencil[] )
     1136{
     1137   ASSERT(n >= 0);
     1138   if (ctx->DrawBuffer->Stencil) {
     1139      if (ctx->Driver.ReadStencilSpan) {
     1140         (*ctx->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil );
     1141      }
     1142      else {
     1143         const GLstencil *s = STENCIL_ADDRESS( x, y );
    10041144#if STENCIL_BITS == 8
    1005       MEMCPY( stencil, s, n * sizeof(GLstencil) );
     1145         MEMCPY( stencil, s, n * sizeof(GLstencil) );
    10061146#else
    1007       GLuint i;
    1008       for (i=0;i<n;i++)
    1009          stencil[i] = s[i];
     1147         GLuint i;
     1148         for (i=0;i<n;i++)
     1149            stencil[i] = s[i];
    10101150#endif
     1151      }
    10111152   }
    10121153}
     
    10161157/*
    10171158 * Write a span of stencil values to the stencil buffer.
     1159 * Used for glDraw/CopyPixels
    10181160 * Input:  n - how many pixels
    1019  *         x,y - location of first pixel
     1161 *         x, y - location of first pixel
    10201162 *         stencil - the array of stencil values
    10211163 */
    10221164void gl_write_stencil_span( GLcontext *ctx,
    1023                             GLuint n, GLint x, GLint y,
    1024                             const GLstencil stencil[] )
    1025 {
    1026    if (ctx->Buffer->Stencil) {
    1027       GLstencil *s = STENCIL_ADDRESS( x, y );
     1165                            GLint n, GLint x, GLint y,
     1166                            const GLstencil stencil[] )
     1167{
     1168   ASSERT(n >= 0);
     1169   if (ctx->DrawBuffer->Stencil) {
     1170      /* do clipping */
     1171      if (y < ctx->DrawBuffer->Ymin || y > ctx->DrawBuffer->Ymax)
     1172         return;
     1173      if (x < ctx->DrawBuffer->Xmin) {
     1174         GLint diff = ctx->DrawBuffer->Xmin - x;
     1175         n -= diff;
     1176         stencil += diff;
     1177         x = ctx->DrawBuffer->Xmin;
     1178      }
     1179      if (x + n > ctx->DrawBuffer->Xmax) {
     1180         GLint diff = x + n - ctx->DrawBuffer->Xmax;
     1181         n -= diff;
     1182      }
     1183
     1184      ASSERT( n >= 0);
     1185
     1186      if (ctx->Driver.WriteStencilSpan) {
     1187         (*ctx->Driver.WriteStencilSpan)( ctx, n, x, y, stencil, NULL );
     1188      }
     1189      else {
     1190         GLstencil *s = STENCIL_ADDRESS( x, y );
    10281191#if STENCIL_BITS == 8
    1029       MEMCPY( s, stencil, n * sizeof(GLstencil) );
     1192         MEMCPY( s, stencil, n * sizeof(GLstencil) );
    10301193#else
    1031       GLuint i;
    1032       for (i=0;i<n;i++)
    1033          s[i] = stencil[i];
     1194         GLuint i;
     1195         for (i=0;i<n;i++)
     1196            s[i] = stencil[i];
    10341197#endif
     1198      }
    10351199   }
    10361200}
     
    10441208void gl_alloc_stencil_buffer( GLcontext *ctx )
    10451209{
    1046    GLuint buffersize = ctx->Buffer->Width * ctx->Buffer->Height;
     1210   GLuint buffersize = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
    10471211
    10481212   /* deallocate current stencil buffer if present */
    1049    if (ctx->Buffer->Stencil) {
    1050       FREE(ctx->Buffer->Stencil);
    1051       ctx->Buffer->Stencil = NULL;
     1213   if (ctx->DrawBuffer->Stencil) {
     1214      FREE(ctx->DrawBuffer->Stencil);
     1215      ctx->DrawBuffer->Stencil = NULL;
    10521216   }
    10531217
    10541218   /* allocate new stencil buffer */
    1055    ctx->Buffer->Stencil = (GLstencil *) MALLOC(buffersize * sizeof(GLstencil));
    1056    if (!ctx->Buffer->Stencil) {
     1219   ctx->DrawBuffer->Stencil = (GLstencil *) MALLOC(buffersize * sizeof(GLstencil));
     1220   if (!ctx->DrawBuffer->Stencil) {
    10571221      /* out of memory */
    1058       gl_set_enable( ctx, GL_STENCIL_TEST, GL_FALSE );
     1222      _mesa_set_enable( ctx, GL_STENCIL_TEST, GL_FALSE );
    10591223      gl_error( ctx, GL_OUT_OF_MEMORY, "gl_alloc_stencil_buffer" );
    10601224   }
     
    10631227
    10641228
    1065 
    10661229/*
    1067  * Clear the stencil buffer.  If the stencil buffer doesn't exist yet we'll
    1068  * allocate it now.
     1230 * Clear the software (malloc'd) stencil buffer.
    10691231 */
    1070 void gl_clear_stencil_buffer( GLcontext *ctx )
    1071 {
    1072    if (ctx->Visual->StencilBits==0 || !ctx->Buffer->Stencil) {
     1232static void
     1233clear_software_stencil_buffer( GLcontext *ctx )
     1234{
     1235   if (ctx->Visual->StencilBits==0 || !ctx->DrawBuffer->Stencil) {
    10731236      /* no stencil buffer */
    10741237      return;
     
    10771240   if (ctx->Scissor.Enabled) {
    10781241      /* clear scissor region only */
    1079       const GLint width = ctx->Buffer->Xmax - ctx->Buffer->Xmin + 1;
     1242      const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin + 1;
    10801243      if (ctx->Stencil.WriteMask != STENCIL_MAX) {
    10811244         /* must apply mask to the clear */
    10821245         GLint y;
    1083          for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
    1084             GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );
    1085             GLint x;
     1246         for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) {
    10861247            const GLstencil mask = ctx->Stencil.WriteMask;
    10871248            const GLstencil invMask = ~mask;
    10881249            const GLstencil clearVal = (ctx->Stencil.Clear & mask);
    1089             for (x = 0; x < width; x++) {
    1090                ptr[x] = (ptr[x] & invMask) | clearVal;
     1250            GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->Xmin, y );
     1251            GLint i;
     1252            for (i = 0; i < width; i++) {
     1253               stencil[i] = (stencil[i] & invMask) | clearVal;
    10911254            }
    10921255         }
     
    10951258         /* no masking */
    10961259         GLint y;
    1097          for (y=ctx->Buffer->Ymin; y<=ctx->Buffer->Ymax; y++) {
    1098             GLstencil *ptr = STENCIL_ADDRESS( ctx->Buffer->Xmin, y );
     1260         for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) {
     1261            GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->Xmin, y );
    10991262#if STENCIL_BITS==8
    1100             MEMSET( ptr, ctx->Stencil.Clear, width * sizeof(GLstencil) );
     1263            MEMSET( stencil, ctx->Stencil.Clear, width * sizeof(GLstencil) );
    11011264#else
    1102             GLint x;
    1103             for (x = 0; x < width; x++)
    1104                ptr[x] = ctx->Stencil.Clear;
     1265            GLint i;
     1266            for (i = 0; i < width; i++)
     1267               stencil[x] = ctx->Stencil.Clear;
    11051268#endif
    11061269         }
     
    11111274      if (ctx->Stencil.WriteMask != STENCIL_MAX) {
    11121275         /* must apply mask to the clear */
    1113          const GLuint n = ctx->Buffer->Width * ctx->Buffer->Height;
    1114          GLstencil *buffer = ctx->Buffer->Stencil;
     1276         const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
     1277         GLstencil *stencil = ctx->DrawBuffer->Stencil;
    11151278         const GLstencil mask = ctx->Stencil.WriteMask;
    11161279         const GLstencil invMask = ~mask;
     
    11181281         GLuint i;
    11191282         for (i = 0; i < n; i++) {
    1120             buffer[i] = (buffer[i] & invMask) | clearVal;
     1283            stencil[i] = (stencil[i] & invMask) | clearVal;
    11211284         }
    11221285      }
    11231286      else {
    11241287         /* clear whole buffer without masking */
    1125          const GLuint n = ctx->Buffer->Width * ctx->Buffer->Height;
    1126          GLstencil *buffer = ctx->Buffer->Stencil;
     1288         const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height;
     1289         GLstencil *stencil = ctx->DrawBuffer->Stencil;
    11271290
    11281291#if STENCIL_BITS==8
    1129          MEMSET(buffer, ctx->Stencil.Clear, n * sizeof(GLstencil) );
     1292         MEMSET(stencil, ctx->Stencil.Clear, n * sizeof(GLstencil) );
    11301293#else
    11311294         GLuint i;
    11321295         for (i = 0; i < n; i++) {
    1133             buffer[i] = ctx->Stencil.Clear;
     1296            stencil[i] = ctx->Stencil.Clear;
    11341297         }
    11351298#endif
     
    11371300   }
    11381301}
     1302
     1303
     1304
     1305/*
     1306 * Clear the hardware (in graphics card) stencil buffer.
     1307 * This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan()
     1308 * functions.
     1309 * Actually, if there is a hardware stencil buffer it really should have
     1310 * been cleared in Driver.Clear()!  However, if the hardware does not
     1311 * support scissored clears or masked clears (i.e. glStencilMask) then
     1312 * we have to use the span-based functions.
     1313 */
     1314static void
     1315clear_hardware_stencil_buffer( GLcontext *ctx )
     1316{
     1317   ASSERT(ctx->Driver.WriteStencilSpan);
     1318   ASSERT(ctx->Driver.ReadStencilSpan);
     1319
     1320   if (ctx->Scissor.Enabled) {
     1321      /* clear scissor region only */
     1322      const GLint x = ctx->DrawBuffer->Xmin;
     1323      const GLint width = ctx->DrawBuffer->Xmax - ctx->DrawBuffer->Xmin + 1;
     1324      if (ctx->Stencil.WriteMask != STENCIL_MAX) {
     1325         /* must apply mask to the clear */
     1326         GLint y;
     1327         for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) {
     1328            const GLstencil mask = ctx->Stencil.WriteMask;
     1329            const GLstencil invMask = ~mask;
     1330            const GLstencil clearVal = (ctx->Stencil.Clear & mask);
     1331            GLstencil stencil[MAX_WIDTH];
     1332            GLint i;
     1333            (*ctx->Driver.ReadStencilSpan)(ctx, x, y, width, stencil);
     1334            for (i = 0; i < width; i++) {
     1335               stencil[i] = (stencil[i] & invMask) | clearVal;
     1336            }
     1337            (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
     1338         }
     1339      }
     1340      else {
     1341         /* no masking */
     1342         GLstencil stencil[MAX_WIDTH];
     1343         GLint y, i;
     1344         for (i = 0; i < width; i++) {
     1345            stencil[i] = ctx->Stencil.Clear;
     1346         }
     1347         for (y = ctx->DrawBuffer->Ymin; y <= ctx->DrawBuffer->Ymax; y++) {
     1348            (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
     1349         }
     1350      }
     1351   }
     1352   else {
     1353      /* clear whole stencil buffer */
     1354      if (ctx->Stencil.WriteMask != STENCIL_MAX) {
     1355         /* must apply mask to the clear */
     1356         const GLstencil mask = ctx->Stencil.WriteMask;
     1357         const GLstencil invMask = ~mask;
     1358         const GLstencil clearVal = (ctx->Stencil.Clear & mask);
     1359         const GLint width = ctx->DrawBuffer->Width;
     1360         const GLint height = ctx->DrawBuffer->Height;
     1361         const GLint x = ctx->DrawBuffer->Xmin;
     1362         GLint y;
     1363         for (y = 0; y < height; y++) {
     1364            GLstencil stencil[MAX_WIDTH];
     1365            GLuint i;
     1366            (*ctx->Driver.ReadStencilSpan)(ctx, x, y, width, stencil);
     1367            for (i = 0; i < width; i++) {
     1368               stencil[i] = (stencil[i] & invMask) | clearVal;
     1369            }
     1370            (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
     1371         }
     1372      }
     1373      else {
     1374         /* clear whole buffer without masking */
     1375         const GLint width = ctx->DrawBuffer->Width;
     1376         const GLint height = ctx->DrawBuffer->Width;
     1377         const GLint x = ctx->DrawBuffer->Xmin;
     1378         GLstencil stencil[MAX_WIDTH];
     1379         GLint y, i;
     1380         for (i = 0; i < width; i++) {
     1381            stencil[i] = ctx->Stencil.Clear;
     1382         }
     1383         for (y = 0; y < height; y++) {
     1384            (*ctx->Driver.WriteStencilSpan)(ctx, x, y, width, stencil, NULL);
     1385         }
     1386      }
     1387   }
     1388}
     1389
     1390
     1391
     1392/*
     1393 * Clear the stencil buffer.
     1394 */
     1395void gl_clear_stencil_buffer( GLcontext *ctx )
     1396{
     1397   if (ctx->Driver.WriteStencilSpan) {
     1398      ASSERT(ctx->Driver.ReadStencilSpan);
     1399      clear_hardware_stencil_buffer(ctx);
     1400   }
     1401   else {
     1402      clear_software_stencil_buffer(ctx);
     1403   }
     1404}
     1405
Note: See TracChangeset for help on using the changeset viewer.