VirtualBox

Ignore:
Timestamp:
Jan 22, 2013 8:18:51 AM (12 years ago)
Author:
vboxsync
Message:

crOpenGL: 1. stencil state fixes, 2. missing gets

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c

    r15532 r44326  
    1010#include "state_internals.h"
    1111
     12
     13static GLint crStateStencilBufferGetIdxAndCount(CRStencilState *s, GLenum face, GLint *pIdx, GLint *pBitsIdx)
     14{
     15    switch (face)
     16    {
     17        case GL_FRONT_AND_BACK:
     18            *pIdx = 0;
     19            *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK;
     20            return 2;
     21        case GL_FRONT:
     22            *pIdx = CRSTATE_STENCIL_BUFFER_ID_FRONT;
     23            *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT;
     24            return 1;
     25        case GL_BACK:
     26            *pIdx = CRSTATE_STENCIL_BUFFER_ID_BACK;
     27            *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_BACK;
     28            return 1;
     29        case 0:
     30            if (!s->stencilTwoSideEXT || s->activeStencilFace == GL_FRONT)
     31            {
     32                /* both front and back */
     33                *pIdx = 0;
     34                *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK;
     35                return 2;
     36            }
     37            *pIdx = CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK;
     38            *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK;
     39            return 1;
     40        default:
     41            crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilBufferGetIdxAndCount");
     42            return 0;
     43    }
     44    crError("should never be here!");
     45    return 0;
     46}
     47
     48void crStateStencilBufferInit(CRStencilBufferState *s)
     49{
     50    s->func = GL_ALWAYS;
     51    s->mask = 0xFFFFFFFF;
     52    s->ref = 0;
     53
     54    s->fail = GL_KEEP;
     55    s->passDepthFail = GL_KEEP;
     56    s->passDepthPass = GL_KEEP;
     57}
     58
     59static void crStateStencilBufferRefBitsInit(CRContext *ctx, CRStencilBufferRefBits *sb)
     60{
     61    RESET(sb->func, ctx->bitid);
     62    RESET(sb->op, ctx->bitid);
     63}
     64
    1265void crStateStencilInit(CRContext *ctx)
    1366{
     
    1568        CRStateBits *stateb = GetCurrentBits();
    1669        CRStencilBits *sb = &(stateb->stencil);
     70        int i;
    1771
    1872        s->stencilTest = GL_FALSE;
    1973        RESET(sb->enable, ctx->bitid);
    2074
    21         s->func = GL_ALWAYS;
    22         s->mask = 0xFFFFFFFF;
    23         s->ref = 0;
    24         RESET(sb->func, ctx->bitid);
    25 
    26         s->fail = GL_KEEP;
    27         s->passDepthFail = GL_KEEP;
    28         s->passDepthPass = GL_KEEP;
    29         RESET(sb->op, ctx->bitid);
     75    s->stencilTwoSideEXT = GL_FALSE;
     76    RESET(sb->enableTwoSideEXT, ctx->bitid);
     77
     78        s->activeStencilFace = GL_FRONT;
     79        RESET(sb->activeStencilFace, ctx->bitid);
    3080
    3181        s->clearValue = 0;
     
    3686
    3787        RESET(sb->dirty, ctx->bitid);
    38 }
    39 
    40 void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask)
     88
     89        for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i)
     90        {
     91            crStateStencilBufferInit(&s->buffers[i]);
     92        }
     93
     94    for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i)
     95    {
     96        crStateStencilBufferRefBitsInit(ctx, &sb->bufferRefs[i]);
     97    }
     98}
     99
     100static void crStateStencilBufferFunc(CRContext *g, CRStencilBufferState *s, GLenum func, GLint ref, GLuint mask)
     101{
     102    s->func = func;
     103    s->ref = ref;
     104    s->mask = mask;
     105}
     106
     107static void crStateStencilFuncPerform(GLenum face, GLenum func, GLint ref, GLuint mask)
     108{
     109    CRContext *g = GetCurrentContext();
     110    CRStencilState *s = &(g->stencil);
     111    CRStateBits *stateb = GetCurrentBits();
     112    CRStencilBits *sb = &(stateb->stencil);
     113    GLint idx, bitsIdx, count, i;
     114
     115
     116    if (g->current.inBeginEnd)
     117    {
     118        crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
     119            "glStencilFunc called in begin/end");
     120        return;
     121    }
     122
     123    FLUSH();
     124
     125    if (func != GL_NEVER &&
     126        func != GL_LESS &&
     127        func != GL_LEQUAL &&
     128        func != GL_GREATER &&
     129        func != GL_GEQUAL &&
     130        func != GL_EQUAL &&
     131        func != GL_NOTEQUAL &&
     132        func != GL_ALWAYS)
     133    {
     134        crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
     135            "glStencilFunc called with bogu func: %d", func);
     136        return;
     137    }
     138
     139    count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx);
     140    if (count)
     141    {
     142        for (i = idx; i < idx + count; ++i)
     143        {
     144            crStateStencilBufferFunc(g, &s->buffers[i], func, ref, mask);
     145        }
     146        DIRTY(sb->bufferRefs[bitsIdx].func, g->neg_bitid);
     147
     148        DIRTY(sb->dirty, g->neg_bitid);
     149    }
     150}
     151
     152void STATE_APIENTRY crStateStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
     153{
     154    if (!face)
     155    {
     156        /* crStateStencilFuncPerform accepts 0 value, while glStencilFuncSeparate does not,
     157         * filter it out here */
     158        crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilFuncSeparate");
     159        return;
     160    }
     161    crStateStencilFuncPerform(face, func, ref, mask);
     162}
     163
     164void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask)
     165{
     166    crStateStencilFuncPerform(0, func, ref, mask);
     167}
     168
     169static void STATE_APIENTRY crStateStencilBufferOp (CRContext *g, CRStencilBufferState *s, GLenum fail, GLenum zfail, GLenum zpass)
     170{
     171    s->fail = fail;
     172    s->passDepthFail = zfail;
     173    s->passDepthPass = zpass;
     174}
     175
     176static void crStateStencilOpPerform (GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
    41177{
    42178        CRContext *g = GetCurrentContext();
     
    44180        CRStateBits *stateb = GetCurrentBits();
    45181        CRStencilBits *sb = &(stateb->stencil);
    46 
    47 
    48         if (g->current.inBeginEnd)
    49         {
    50                 crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
    51                         "glStencilFunc called in begin/end");
    52                 return;
    53         }
    54 
    55         FLUSH();
    56 
    57         if (func != GL_NEVER &&
    58                 func != GL_LESS &&
    59                 func != GL_LEQUAL &&
    60                 func != GL_GREATER &&
    61                 func != GL_GEQUAL &&
    62                 func != GL_EQUAL &&
    63                 func != GL_NOTEQUAL &&
    64                 func != GL_ALWAYS)
    65         {
    66                 crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
    67                         "glStencilFunc called with bogu func: %d", func);
    68                 return;
    69         }
    70 
    71         s->func = func;
    72         s->ref = ref;
    73         s->mask = mask;
    74 
    75         DIRTY(sb->func, g->neg_bitid);
    76         DIRTY(sb->dirty, g->neg_bitid);
    77 }
    78 
    79 void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
    80 {
    81         CRContext *g = GetCurrentContext();
    82         CRStencilState *s = &(g->stencil);
    83         CRStateBits *stateb = GetCurrentBits();
    84         CRStencilBits *sb = &(stateb->stencil);
     182    GLint idx, bitsIdx, count, i;
    85183
    86184        if (g->current.inBeginEnd)
     
    147245        }
    148246
    149         s->fail = fail;
    150         s->passDepthFail = zfail;
    151         s->passDepthPass = zpass;
    152 
    153         DIRTY(sb->op, g->neg_bitid);
    154         DIRTY(sb->dirty, g->neg_bitid);
    155 }
    156 
     247    count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx);
     248    if (count)
     249    {
     250        for (i = idx; i < idx + count; ++i)
     251        {
     252            crStateStencilBufferOp(g, &s->buffers[i], fail, zfail, zpass);
     253        }
     254
     255        DIRTY(sb->bufferRefs[bitsIdx].op, g->neg_bitid);
     256
     257        DIRTY(sb->dirty, g->neg_bitid);
     258    }
     259}
     260
     261void STATE_APIENTRY crStateStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
     262{
     263    if (!face)
     264    {
     265        /* crStateStencilOpPerform accepts 0 value, while glStencilOpSeparate does not,
     266         * filter it out here */
     267        crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilOpSeparate");
     268        return;
     269    }
     270    crStateStencilOpPerform (0, fail, zfail, zpass);
     271}
     272
     273void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass)
     274{
     275    crStateStencilOpPerform (0, fail, zfail, zpass);
     276}
    157277
    158278void STATE_APIENTRY crStateClearStencil (GLint c)
     
    172292        FLUSH();
    173293
    174 
    175294        s->clearValue = c;
    176295       
     
    200319        DIRTY(sb->dirty, g->neg_bitid);
    201320}
     321
     322void STATE_APIENTRY crStateActiveStencilFaceEXT (GLenum face)
     323{
     324    CRContext *g = GetCurrentContext();
     325    CRStencilState *s = &(g->stencil);
     326    CRStateBits *stateb = GetCurrentBits();
     327    CRStencilBits *sb = &(stateb->stencil);
     328
     329    switch (face)
     330    {
     331    case GL_FRONT:
     332    case GL_BACK:
     333        s->activeStencilFace = face;
     334        break;
     335    default:
     336        crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateActiveStencilFaceEXT");
     337        return;
     338    }
     339
     340    DIRTY(sb->activeStencilFace, g->neg_bitid);
     341    DIRTY(sb->dirty, g->neg_bitid);
     342}
     343
     344#define CR_STATE_STENCIL_FUNC_MATCH(_s1, _i1, _s2, _i2) (\
     345    (_s1)->buffers[(_i1)].func == (_s2)->buffers[(_i2)].func && \
     346    (_s1)->buffers[(_i1)].ref  == (_s2)->buffers[(_i2)].ref  && \
     347    (_s1)->buffers[(_i1)].mask == (_s2)->buffers[(_i2)].mask)
     348
     349#define CR_STATE_STENCIL_FUNC_COPY(_s1, _i1, _s2, _i2) do { \
     350        (_s1)->buffers[(_i1)].func = (_s2)->buffers[(_i2)].func; \
     351        (_s1)->buffers[(_i1)].ref  = (_s2)->buffers[(_i2)].ref; \
     352        (_s1)->buffers[(_i1)].mask = (_s2)->buffers[(_i2)].mask; \
     353    } while (0)
     354
     355
     356#define CR_STATE_STENCIL_OP_MATCH(_s1, _i1, _s2, _i2) (\
     357        (_s1)->buffers[(_i1)].fail == (_s2)->buffers[(_i2)].fail && \
     358        (_s1)->buffers[(_i1)].passDepthFail  == (_s2)->buffers[(_i2)].passDepthFail  && \
     359        (_s1)->buffers[(_i1)].passDepthPass == (_s2)->buffers[(_i2)].passDepthPass)
     360
     361#define CR_STATE_STENCIL_OP_COPY(_s1, _i1, _s2, _i2) do { \
     362        (_s1)->buffers[(_i1)].fail = (_s2)->buffers[(_i2)].fail; \
     363        (_s1)->buffers[(_i1)].passDepthFail  = (_s2)->buffers[(_i2)].passDepthFail; \
     364        (_s1)->buffers[(_i1)].passDepthPass = (_s2)->buffers[(_i2)].passDepthPass; \
     365    } while (0)
     366
     367
     368void crStateStencilDiff(CRStencilBits *b, CRbitvalue *bitID,
     369        CRContext *fromCtx, CRContext *toCtx)
     370{
     371    CRStencilState *from = &(fromCtx->stencil);
     372    CRStencilState *to = &(toCtx->stencil);
     373    unsigned int j, i;
     374    GLenum activeFace;
     375    GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty;
     376    GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
     377    CRbitvalue nbitID[CR_MAX_BITARRAY];
     378    for (j=0;j<CR_MAX_BITARRAY;j++)
     379        nbitID[j] = ~bitID[j];
     380    i = 0; /* silence compiler */
     381
     382    if (CHECKDIRTY(b->enable, bitID))
     383    {
     384        glAble able[2];
     385        able[0] = diff_api.Disable;
     386        able[1] = diff_api.Enable;
     387        if (from->stencilTest != to->stencilTest)
     388        {
     389            able[to->stencilTest](GL_STENCIL_TEST);
     390            from->stencilTest = to->stencilTest;
     391        }
     392        CLEARDIRTY(b->enable, nbitID);
     393    }
     394
     395    if (CHECKDIRTY(b->enableTwoSideEXT, bitID))
     396    {
     397        glAble able[2];
     398        able[0] = diff_api.Disable;
     399        able[1] = diff_api.Enable;
     400        if (from->stencilTwoSideEXT != to->stencilTwoSideEXT)
     401        {
     402            able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT);
     403            from->stencilTwoSideEXT = to->stencilTwoSideEXT;
     404        }
     405        CLEARDIRTY(b->enableTwoSideEXT, nbitID);
     406    }
     407
     408    if (CHECKDIRTY(b->clearValue, bitID))
     409    {
     410        if (from->clearValue != to->clearValue)
     411        {
     412            diff_api.ClearStencil (to->clearValue);
     413            from->clearValue = to->clearValue;
     414        }
     415        CLEARDIRTY(b->clearValue, nbitID);
     416    }
     417
     418    activeFace = to->activeStencilFace;
     419
     420
     421    /* func */
     422    frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID);
     423    frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID);
     424    backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID);
     425#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \
     426        frontMatch >= 0 ? \
     427                frontMatch \
     428                : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
     429
     430#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \
     431        backMatch >= 0 ? \
     432                backMatch \
     433                : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     434
     435#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \
     436        toFrontBackMatch >= 0 ? \
     437                toFrontBackMatch \
     438                : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     439
     440    if (frontBackDirty)
     441    {
     442        if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()
     443                || !CR_STATE_STENCIL_FUNC_BACK_MATCH())
     444        {
     445            if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
     446            {
     447                if (activeFace == GL_BACK)
     448                {
     449                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     450                    activeFace = GL_FRONT;
     451                }
     452
     453                diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     454                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     455                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     456
     457                CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     458                CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     459                frontIsSet = GL_TRUE;
     460                backIsSet = GL_TRUE;
     461            }
     462            else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     463            {
     464                if (activeFace == GL_BACK)
     465                {
     466                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     467                    activeFace = GL_FRONT;
     468                }
     469
     470                diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     471                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     472                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     473
     474                CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     475                frontIsSet = GL_TRUE;
     476            }
     477            else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
     478            {
     479                if (activeFace == GL_BACK)
     480                {
     481                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     482                    activeFace = GL_FRONT;
     483                }
     484
     485                diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
     486                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
     487                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
     488
     489                CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
     490
     491                backIsSet = GL_TRUE;
     492            }
     493        }
     494
     495        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID);
     496    }
     497
     498    if (frontDirty)
     499    {
     500        if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     501        {
     502            if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
     503            {
     504                if (!frontIsSet || !backIsSet)
     505                {
     506                    if (activeFace == GL_BACK)
     507                    {
     508                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     509                        activeFace = GL_FRONT;
     510                    }
     511
     512                    diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     513                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     514                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     515
     516                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     517                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     518
     519                    frontIsSet = GL_TRUE;
     520                    backIsSet = GL_TRUE;
     521                }
     522            }
     523            else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     524            {
     525                if (!frontIsSet)
     526                {
     527                    if (activeFace == GL_BACK)
     528                    {
     529                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     530                        activeFace = GL_FRONT;
     531                    }
     532
     533                    diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     534                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     535                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     536
     537                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     538                    frontIsSet = GL_TRUE;
     539                }
     540            }
     541            else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
     542            {
     543                if (!backIsSet)
     544                {
     545                    if (activeFace == GL_BACK)
     546                    {
     547                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     548                        activeFace = GL_FRONT;
     549                    }
     550
     551                    diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
     552                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
     553                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
     554                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
     555                    backIsSet = GL_TRUE;
     556                }
     557            }
     558        }
     559        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID);
     560    }
     561
     562
     563    if (backDirty)
     564    {
     565        if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     566        {
     567            if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
     568            {
     569                if (!frontIsSet || !backIsSet)
     570                {
     571                    if (activeFace == GL_BACK)
     572                    {
     573                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     574                        activeFace = GL_FRONT;
     575                    }
     576
     577                    diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     578                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     579                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     580
     581                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     582                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     583
     584                    frontIsSet = GL_TRUE;
     585                    backIsSet = GL_TRUE;
     586                }
     587            }
     588            else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     589            {
     590                if (!frontIsSet)
     591                {
     592                    if (activeFace == GL_BACK)
     593                    {
     594                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     595                        activeFace = GL_FRONT;
     596                    }
     597
     598                    diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     599                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     600                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     601
     602                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     603                    frontIsSet = GL_TRUE;
     604                }
     605            }
     606            else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
     607            {
     608                if (!backIsSet)
     609                {
     610                    if (activeFace == GL_BACK)
     611                    {
     612                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     613                        activeFace = GL_FRONT;
     614                    }
     615
     616                    diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
     617                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
     618                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
     619                    CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
     620                    backIsSet = GL_TRUE;
     621                }
     622            }
     623        }
     624        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID);
     625    }
     626
     627    if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID))
     628    {
     629        if (CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK))
     630        {
     631            if (activeFace == GL_FRONT)
     632            {
     633                diff_api.ActiveStencilFaceEXT(GL_BACK);
     634                activeFace = GL_BACK;
     635            }
     636
     637            diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func,
     638                to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].ref,
     639                to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].mask);
     640            CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK);
     641        }
     642        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID);
     643    }
     644
     645#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH
     646#undef CR_STATE_STENCIL_FUNC_BACK_MATCH
     647#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH
     648
     649    /* op */
     650    backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
     651    frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
     652    frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID);
     653    frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID);
     654    backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID);
     655
     656#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \
     657        frontMatch >= 0 ? \
     658                frontMatch \
     659                : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
     660
     661#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \
     662        backMatch >= 0 ? \
     663                backMatch \
     664                : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     665
     666#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \
     667        toFrontBackMatch >= 0 ? \
     668                toFrontBackMatch \
     669                : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     670
     671    if (frontBackDirty)
     672    {
     673        if (!CR_STATE_STENCIL_OP_FRONT_MATCH()
     674                || !CR_STATE_STENCIL_OP_BACK_MATCH())
     675        {
     676            if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
     677            {
     678                if (activeFace == GL_BACK)
     679                {
     680                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     681                    activeFace = GL_FRONT;
     682                }
     683
     684                diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     685                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     686                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     687
     688                CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     689                CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     690
     691                frontIsSet = GL_TRUE;
     692                backIsSet = GL_TRUE;
     693            }
     694            else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     695            {
     696                if (activeFace == GL_BACK)
     697                {
     698                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     699                    activeFace = GL_FRONT;
     700                }
     701
     702                diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     703                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     704                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     705                CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     706                frontIsSet = GL_TRUE;
     707            }
     708            else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
     709            {
     710                if (activeFace == GL_BACK)
     711                {
     712                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     713                    activeFace = GL_FRONT;
     714                }
     715
     716                diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
     717                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
     718                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
     719                CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
     720                backIsSet = GL_TRUE;
     721            }
     722        }
     723
     724        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID);
     725    }
     726
     727    if (frontDirty)
     728    {
     729        if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     730        {
     731            if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
     732            {
     733                if (!frontIsSet || !backIsSet)
     734                {
     735                    if (activeFace == GL_BACK)
     736                    {
     737                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     738                        activeFace = GL_FRONT;
     739                    }
     740
     741                    diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     742                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     743                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     744
     745                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     746                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     747
     748                    frontIsSet = GL_TRUE;
     749                    backIsSet = GL_TRUE;
     750                }
     751            }
     752            else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     753            {
     754                if (!frontIsSet)
     755                {
     756                    if (activeFace == GL_BACK)
     757                    {
     758                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     759                        activeFace = GL_FRONT;
     760                    }
     761
     762                    diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     763                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     764                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     765
     766                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     767
     768                    frontIsSet = GL_TRUE;
     769                }
     770            }
     771            else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
     772            {
     773                if (!backIsSet)
     774                {
     775                    if (activeFace == GL_BACK)
     776                    {
     777                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     778                        activeFace = GL_FRONT;
     779                    }
     780
     781                    diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
     782                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
     783                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
     784                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
     785                    backIsSet = GL_TRUE;
     786                }
     787            }
     788        }
     789        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID);
     790    }
     791
     792
     793    if (backDirty)
     794    {
     795        if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     796        {
     797            if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
     798            {
     799                if (!frontIsSet || !backIsSet)
     800                {
     801                    if (activeFace == GL_BACK)
     802                    {
     803                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     804                        activeFace = GL_FRONT;
     805                    }
     806
     807                    diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     808                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     809                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     810
     811                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     812                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     813
     814                    frontIsSet = GL_TRUE;
     815                    backIsSet = GL_TRUE;
     816                }
     817            }
     818            else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     819            {
     820                if (!frontIsSet)
     821                {
     822                    if (activeFace == GL_BACK)
     823                    {
     824                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     825                        activeFace = GL_FRONT;
     826                    }
     827
     828                    diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     829                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     830                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     831
     832                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT);
     833
     834                    frontIsSet = GL_TRUE;
     835                }
     836            }
     837            else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
     838            {
     839                if (!backIsSet)
     840                {
     841                    if (activeFace == GL_BACK)
     842                    {
     843                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     844                        activeFace = GL_FRONT;
     845                    }
     846
     847                    diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
     848                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
     849                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
     850                    CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK);
     851                    backIsSet = GL_TRUE;
     852                }
     853            }
     854        }
     855        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID);
     856    }
     857
     858    if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID))
     859    {
     860        if (CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK))
     861        {
     862            if (activeFace == GL_FRONT)
     863            {
     864                diff_api.ActiveStencilFaceEXT(GL_BACK);
     865                activeFace = GL_BACK;
     866            }
     867
     868            diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].fail,
     869                                    to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].passDepthFail,
     870                                    to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].passDepthPass);
     871            CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK);
     872        }
     873        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID);
     874    }
     875
     876#undef CR_STATE_STENCIL_OP_FRONT_MATCH
     877#undef CR_STATE_STENCIL_OP_BACK_MATCH
     878#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH
     879
     880
     881    if (activeFace != to->activeStencilFace)
     882    {
     883        diff_api.ActiveStencilFaceEXT(activeFace);
     884    }
     885
     886    if (CHECKDIRTY(b->activeStencilFace, bitID))
     887    {
     888        if (from->activeStencilFace != to->activeStencilFace)
     889        {
     890            /* we already did it ( see above )*/
     891            /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */
     892            from->activeStencilFace = to->activeStencilFace;
     893        }
     894        CLEARDIRTY(b->activeStencilFace, nbitID);
     895    }
     896
     897    if (CHECKDIRTY(b->writeMask, bitID))
     898    {
     899        if (from->writeMask != to->writeMask)
     900        {
     901            diff_api.StencilMask (to->writeMask);
     902            from->writeMask = to->writeMask;
     903        }
     904        CLEARDIRTY(b->writeMask, nbitID);
     905    }
     906    CLEARDIRTY(b->dirty, nbitID);
     907}
     908
     909void crStateStencilSwitch(CRStencilBits *b, CRbitvalue *bitID,
     910        CRContext *fromCtx, CRContext *toCtx)
     911{
     912    CRStencilState *from = &(fromCtx->stencil);
     913    CRStencilState *to = &(toCtx->stencil);
     914    unsigned int j, i;
     915    GLenum activeFace;
     916    GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty;
     917    GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
     918    CRbitvalue nbitID[CR_MAX_BITARRAY];
     919    for (j=0;j<CR_MAX_BITARRAY;j++)
     920        nbitID[j] = ~bitID[j];
     921    i = 0; /* silence compiler */
     922
     923    if (CHECKDIRTY(b->enable, bitID))
     924    {
     925        glAble able[2];
     926        able[0] = diff_api.Disable;
     927        able[1] = diff_api.Enable;
     928        if (from->stencilTest != to->stencilTest)
     929        {
     930            able[to->stencilTest](GL_STENCIL_TEST);
     931            FILLDIRTY(b->enable);
     932            FILLDIRTY(b->dirty);
     933        }
     934        CLEARDIRTY(b->enable, nbitID);
     935    }
     936    if (CHECKDIRTY(b->enableTwoSideEXT, bitID))
     937    {
     938        glAble able[2];
     939        able[0] = diff_api.Disable;
     940        able[1] = diff_api.Enable;
     941        if (from->stencilTwoSideEXT != to->stencilTwoSideEXT)
     942        {
     943            able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT);
     944            FILLDIRTY(b->enableTwoSideEXT);
     945            FILLDIRTY(b->dirty);
     946        }
     947        CLEARDIRTY(b->enableTwoSideEXT, nbitID);
     948    }
     949    if (CHECKDIRTY(b->clearValue, bitID))
     950    {
     951        if (from->clearValue != to->clearValue)
     952        {
     953            diff_api.ClearStencil (to->clearValue);
     954            FILLDIRTY(b->clearValue);
     955            FILLDIRTY(b->dirty);
     956        }
     957        CLEARDIRTY(b->clearValue, nbitID);
     958    }
     959
     960    activeFace = from->activeStencilFace;
     961
     962    /* func */
     963    frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID);
     964    frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID);
     965    backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID);
     966#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \
     967        frontMatch >= 0 ? \
     968                frontMatch \
     969                : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
     970
     971#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \
     972        backMatch >= 0 ? \
     973                backMatch \
     974                : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     975
     976#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \
     977        toFrontBackMatch >= 0 ? \
     978                toFrontBackMatch \
     979                : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     980
     981    if (frontBackDirty)
     982    {
     983        if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()
     984                || !CR_STATE_STENCIL_FUNC_BACK_MATCH())
     985        {
     986            if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
     987            {
     988                if (activeFace == GL_BACK)
     989                {
     990                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     991                    activeFace = GL_FRONT;
     992                }
     993
     994                diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     995                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     996                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     997
     998                frontIsSet = GL_TRUE;
     999                backIsSet = GL_TRUE;
     1000            }
     1001            else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     1002            {
     1003                if (activeFace == GL_BACK)
     1004                {
     1005                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1006                    activeFace = GL_FRONT;
     1007                }
     1008
     1009                diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     1010                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     1011                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     1012                frontIsSet = GL_TRUE;
     1013            }
     1014            else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
     1015            {
     1016                if (activeFace == GL_BACK)
     1017                {
     1018                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1019                    activeFace = GL_FRONT;
     1020                }
     1021
     1022                diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
     1023                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
     1024                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
     1025                backIsSet = GL_TRUE;
     1026            }
     1027            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func);
     1028            FILLDIRTY(b->dirty);
     1029        }
     1030
     1031        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID);
     1032    }
     1033
     1034    if (frontDirty)
     1035    {
     1036        if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     1037        {
     1038            if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
     1039            {
     1040                if (!frontIsSet || !backIsSet)
     1041                {
     1042                    if (activeFace == GL_BACK)
     1043                    {
     1044                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1045                        activeFace = GL_FRONT;
     1046                    }
     1047
     1048                    diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     1049                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     1050                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     1051
     1052                    frontIsSet = GL_TRUE;
     1053                    backIsSet = GL_TRUE;
     1054                }
     1055            }
     1056            else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     1057            {
     1058                if (!frontIsSet)
     1059                {
     1060                    if (activeFace == GL_BACK)
     1061                    {
     1062                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1063                        activeFace = GL_FRONT;
     1064                    }
     1065
     1066                    diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     1067                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     1068                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     1069                    frontIsSet = GL_TRUE;
     1070                }
     1071            }
     1072            else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
     1073            {
     1074                if (!backIsSet)
     1075                {
     1076                    if (activeFace == GL_BACK)
     1077                    {
     1078                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1079                        activeFace = GL_FRONT;
     1080                    }
     1081
     1082                    diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
     1083                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
     1084                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
     1085                    backIsSet = GL_TRUE;
     1086                }
     1087            }
     1088            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func);
     1089            FILLDIRTY(b->dirty);
     1090        }
     1091        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID);
     1092    }
     1093
     1094
     1095    if (backDirty)
     1096    {
     1097        if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
     1098        {
     1099            if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH())
     1100            {
     1101                if (!frontIsSet || !backIsSet)
     1102                {
     1103                    if (activeFace == GL_BACK)
     1104                    {
     1105                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1106                        activeFace = GL_FRONT;
     1107                    }
     1108
     1109                    diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     1110                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     1111                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     1112
     1113                    frontIsSet = GL_TRUE;
     1114                    backIsSet = GL_TRUE;
     1115                }
     1116            }
     1117            else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH())
     1118            {
     1119                if (!frontIsSet)
     1120                {
     1121                    if (activeFace == GL_BACK)
     1122                    {
     1123                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1124                        activeFace = GL_FRONT;
     1125                    }
     1126
     1127                    diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func,
     1128                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref,
     1129                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask);
     1130                    frontIsSet = GL_TRUE;
     1131                }
     1132            }
     1133            else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH())
     1134            {
     1135                if (!backIsSet)
     1136                {
     1137                    if (activeFace == GL_BACK)
     1138                    {
     1139                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1140                        activeFace = GL_FRONT;
     1141                    }
     1142
     1143                    diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func,
     1144                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref,
     1145                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask);
     1146                    backIsSet = GL_TRUE;
     1147                }
     1148            }
     1149            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func);
     1150            FILLDIRTY(b->dirty);
     1151        }
     1152        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID);
     1153    }
     1154
     1155    if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID))
     1156    {
     1157        if (CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK))
     1158        {
     1159            if (activeFace == GL_FRONT)
     1160            {
     1161                diff_api.ActiveStencilFaceEXT(GL_BACK);
     1162                activeFace = GL_BACK;
     1163            }
     1164
     1165            diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func,
     1166                to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].ref,
     1167                to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].mask);
     1168
     1169            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func);
     1170            FILLDIRTY(b->dirty);
     1171        }
     1172        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID);
     1173    }
     1174
     1175#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH
     1176#undef CR_STATE_STENCIL_FUNC_BACK_MATCH
     1177#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH
     1178
     1179    /* op */
     1180    backIsSet = GL_FALSE, frontIsSet = GL_FALSE;
     1181    frontMatch = -1, backMatch = -1, toFrontBackMatch = -1;
     1182    frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID);
     1183    frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID);
     1184    backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID);
     1185
     1186#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \
     1187        frontMatch >= 0 ? \
     1188                frontMatch \
     1189                : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT)))
     1190
     1191#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \
     1192        backMatch >= 0 ? \
     1193                backMatch \
     1194                : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     1195
     1196#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \
     1197        toFrontBackMatch >= 0 ? \
     1198                toFrontBackMatch \
     1199                : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK)))
     1200
     1201    if (frontBackDirty)
     1202    {
     1203        if (!CR_STATE_STENCIL_OP_FRONT_MATCH()
     1204                || !CR_STATE_STENCIL_OP_BACK_MATCH())
     1205        {
     1206            if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
     1207            {
     1208                if (activeFace == GL_BACK)
     1209                {
     1210                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1211                    activeFace = GL_FRONT;
     1212                }
     1213
     1214                diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     1215                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     1216                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     1217
     1218                frontIsSet = GL_TRUE;
     1219                backIsSet = GL_TRUE;
     1220            }
     1221            else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     1222            {
     1223                if (activeFace == GL_BACK)
     1224                {
     1225                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1226                    activeFace = GL_FRONT;
     1227                }
     1228
     1229                diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     1230                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     1231                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     1232                frontIsSet = GL_TRUE;
     1233            }
     1234            else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
     1235            {
     1236                if (activeFace == GL_BACK)
     1237                {
     1238                    diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1239                    activeFace = GL_FRONT;
     1240                }
     1241
     1242                diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
     1243                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
     1244                    to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
     1245                backIsSet = GL_TRUE;
     1246            }
     1247            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op);
     1248            FILLDIRTY(b->dirty);
     1249        }
     1250
     1251        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID);
     1252    }
     1253
     1254    if (frontDirty)
     1255    {
     1256        if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     1257        {
     1258            if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
     1259            {
     1260                if (!frontIsSet || !backIsSet)
     1261                {
     1262                    if (activeFace == GL_BACK)
     1263                    {
     1264                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1265                        activeFace = GL_FRONT;
     1266                    }
     1267
     1268                    diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     1269                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     1270                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     1271
     1272                    frontIsSet = GL_TRUE;
     1273                    backIsSet = GL_TRUE;
     1274                }
     1275            }
     1276            else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     1277            {
     1278                if (!frontIsSet)
     1279                {
     1280                    if (activeFace == GL_BACK)
     1281                    {
     1282                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1283                        activeFace = GL_FRONT;
     1284                    }
     1285
     1286                    diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     1287                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     1288                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     1289                    frontIsSet = GL_TRUE;
     1290                }
     1291            }
     1292            else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
     1293            {
     1294                if (!backIsSet)
     1295                {
     1296                    if (activeFace == GL_BACK)
     1297                    {
     1298                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1299                        activeFace = GL_FRONT;
     1300                    }
     1301
     1302                    diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
     1303                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
     1304                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
     1305                    backIsSet = GL_TRUE;
     1306                }
     1307            }
     1308
     1309            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op);
     1310            FILLDIRTY(b->dirty);
     1311        }
     1312        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID);
     1313    }
     1314
     1315
     1316    if (backDirty)
     1317    {
     1318        if (!CR_STATE_STENCIL_OP_BACK_MATCH())
     1319        {
     1320            if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH())
     1321            {
     1322                if (!frontIsSet || !backIsSet)
     1323                {
     1324                    if (activeFace == GL_BACK)
     1325                    {
     1326                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1327                        activeFace = GL_FRONT;
     1328                    }
     1329
     1330                    diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     1331                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     1332                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     1333
     1334                    frontIsSet = GL_TRUE;
     1335                    backIsSet = GL_TRUE;
     1336                }
     1337            }
     1338            else if (!CR_STATE_STENCIL_OP_FRONT_MATCH())
     1339            {
     1340                if (!frontIsSet)
     1341                {
     1342                    if (activeFace == GL_BACK)
     1343                    {
     1344                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1345                        activeFace = GL_FRONT;
     1346                    }
     1347
     1348                    diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail,
     1349                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail,
     1350                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass);
     1351                    frontIsSet = GL_TRUE;
     1352                }
     1353            }
     1354            else if (!CR_STATE_STENCIL_OP_BACK_MATCH())
     1355            {
     1356                if (!backIsSet)
     1357                {
     1358                    if (activeFace == GL_BACK)
     1359                    {
     1360                        diff_api.ActiveStencilFaceEXT(GL_FRONT);
     1361                        activeFace = GL_FRONT;
     1362                    }
     1363
     1364                    diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail,
     1365                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail,
     1366                        to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass);
     1367                    backIsSet = GL_TRUE;
     1368                }
     1369            }
     1370
     1371            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op);
     1372            FILLDIRTY(b->dirty);
     1373        }
     1374        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID);
     1375    }
     1376
     1377    if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID))
     1378    {
     1379        if (CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK))
     1380        {
     1381            if (activeFace == GL_FRONT)
     1382            {
     1383                diff_api.ActiveStencilFaceEXT(GL_BACK);
     1384                activeFace = GL_BACK;
     1385            }
     1386
     1387            diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].fail,
     1388                                    to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].passDepthFail,
     1389                                    to->buffers[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].passDepthPass);
     1390
     1391            FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op);
     1392            FILLDIRTY(b->dirty);
     1393        }
     1394        CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID);
     1395    }
     1396
     1397#undef CR_STATE_STENCIL_OP_FRONT_MATCH
     1398#undef CR_STATE_STENCIL_OP_BACK_MATCH
     1399#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH
     1400
     1401    if (activeFace != to->activeStencilFace)
     1402    {
     1403        diff_api.ActiveStencilFaceEXT(activeFace);
     1404    }
     1405
     1406    if (CHECKDIRTY(b->activeStencilFace, bitID))
     1407    {
     1408        if (from->activeStencilFace != to->activeStencilFace)
     1409        {
     1410            /* we already did it ( see above )*/
     1411            /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */
     1412            FILLDIRTY(b->activeStencilFace);
     1413            FILLDIRTY(b->dirty);
     1414        }
     1415        CLEARDIRTY(b->activeStencilFace, nbitID);
     1416    }
     1417
     1418    if (CHECKDIRTY(b->writeMask, bitID))
     1419    {
     1420        if (from->writeMask != to->writeMask)
     1421        {
     1422            diff_api.StencilMask (to->writeMask);
     1423            FILLDIRTY(b->writeMask);
     1424            FILLDIRTY(b->dirty);
     1425        }
     1426        CLEARDIRTY(b->writeMask, nbitID);
     1427    }
     1428
     1429    CLEARDIRTY(b->dirty, nbitID);
     1430}
     1431
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette