diff options
| author | Lorry Tar Creator <lorry-tar-importer@baserock.org> | 2014-03-26 19:21:20 +0000 |
|---|---|---|
| committer | <> | 2014-05-08 15:03:54 +0000 |
| commit | fb123f93f9f5ce42c8e5785d2f8e0edaf951740e (patch) | |
| tree | c2103d76aec5f1f10892cd1d3a38e24f665ae5db /src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c | |
| parent | 58ed4748338f9466599adfc8a9171280ed99e23f (diff) | |
| download | VirtualBox-master.tar.gz | |
Imported from /home/lorry/working-area/delta_VirtualBox/VirtualBox-4.3.10.tar.bz2.HEADVirtualBox-4.3.10master
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c')
| -rw-r--r-- | src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c | 1335 |
1 files changed, 1290 insertions, 45 deletions
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c index e284b31a..d543e301 100644 --- a/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c +++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_stencil.c @@ -9,24 +9,74 @@ #include "state/cr_statetypes.h" #include "state_internals.h" + +static GLint crStateStencilBufferGetIdxAndCount(CRStencilState *s, GLenum face, GLint *pIdx, GLint *pBitsIdx) +{ + switch (face) + { + case GL_FRONT_AND_BACK: + *pIdx = 0; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK; + return 2; + case GL_FRONT: + *pIdx = CRSTATE_STENCIL_BUFFER_ID_FRONT; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT; + return 1; + case GL_BACK: + *pIdx = CRSTATE_STENCIL_BUFFER_ID_BACK; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_BACK; + return 1; + case 0: + if (!s->stencilTwoSideEXT || s->activeStencilFace == GL_FRONT) + { + /* both front and back */ + *pIdx = 0; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK; + return 2; + } + *pIdx = CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK; + *pBitsIdx = CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK; + return 1; + default: + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilBufferGetIdxAndCount"); + return 0; + } + crError("should never be here!"); + return 0; +} + +void crStateStencilBufferInit(CRStencilBufferState *s) +{ + s->func = GL_ALWAYS; + s->mask = 0xFFFFFFFF; + s->ref = 0; + + s->fail = GL_KEEP; + s->passDepthFail = GL_KEEP; + s->passDepthPass = GL_KEEP; +} + +static void crStateStencilBufferRefBitsInit(CRContext *ctx, CRStencilBufferRefBits *sb) +{ + RESET(sb->func, ctx->bitid); + RESET(sb->op, ctx->bitid); +} + void crStateStencilInit(CRContext *ctx) { CRStencilState *s = &ctx->stencil; CRStateBits *stateb = GetCurrentBits(); CRStencilBits *sb = &(stateb->stencil); + int i; s->stencilTest = GL_FALSE; RESET(sb->enable, ctx->bitid); - s->func = GL_ALWAYS; - s->mask = 0xFFFFFFFF; - s->ref = 0; - RESET(sb->func, ctx->bitid); + s->stencilTwoSideEXT = GL_FALSE; + RESET(sb->enableTwoSideEXT, ctx->bitid); - s->fail = GL_KEEP; - s->passDepthFail = GL_KEEP; - s->passDepthPass = GL_KEEP; - RESET(sb->op, ctx->bitid); + s->activeStencilFace = GL_FRONT; + RESET(sb->activeStencilFace, ctx->bitid); s->clearValue = 0; RESET(sb->clearValue, ctx->bitid); @@ -35,53 +85,101 @@ void crStateStencilInit(CRContext *ctx) RESET(sb->writeMask, ctx->bitid); RESET(sb->dirty, ctx->bitid); + + for (i = 0; i < CRSTATE_STENCIL_BUFFER_COUNT; ++i) + { + crStateStencilBufferInit(&s->buffers[i]); + } + + for (i = 0; i < CRSTATE_STENCIL_BUFFER_REF_COUNT; ++i) + { + crStateStencilBufferRefBitsInit(ctx, &sb->bufferRefs[i]); + } } -void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask) +static void crStateStencilBufferFunc(CRContext *g, CRStencilBufferState *s, GLenum func, GLint ref, GLuint mask) { - CRContext *g = GetCurrentContext(); - CRStencilState *s = &(g->stencil); - CRStateBits *stateb = GetCurrentBits(); - CRStencilBits *sb = &(stateb->stencil); + s->func = func; + s->ref = ref; + s->mask = mask; +} +static void crStateStencilFuncPerform(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + CRContext *g = GetCurrentContext(); + CRStencilState *s = &(g->stencil); + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + GLint idx, bitsIdx, count, i; - if (g->current.inBeginEnd) - { - crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, - "glStencilFunc called in begin/end"); - return; - } - FLUSH(); + if (g->current.inBeginEnd) + { + crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, + "glStencilFunc called in begin/end"); + return; + } - if (func != GL_NEVER && - func != GL_LESS && - func != GL_LEQUAL && - func != GL_GREATER && - func != GL_GEQUAL && - func != GL_EQUAL && - func != GL_NOTEQUAL && - func != GL_ALWAYS) - { - crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, - "glStencilFunc called with bogu func: %d", func); - return; - } + FLUSH(); - s->func = func; - s->ref = ref; - s->mask = mask; + if (func != GL_NEVER && + func != GL_LESS && + func != GL_LEQUAL && + func != GL_GREATER && + func != GL_GEQUAL && + func != GL_EQUAL && + func != GL_NOTEQUAL && + func != GL_ALWAYS) + { + crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, + "glStencilFunc called with bogu func: %d", func); + return; + } - DIRTY(sb->func, g->neg_bitid); - DIRTY(sb->dirty, g->neg_bitid); + count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx); + if (count) + { + for (i = idx; i < idx + count; ++i) + { + crStateStencilBufferFunc(g, &s->buffers[i], func, ref, mask); + } + DIRTY(sb->bufferRefs[bitsIdx].func, g->neg_bitid); + + DIRTY(sb->dirty, g->neg_bitid); + } +} + +void STATE_APIENTRY crStateStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask) +{ + if (!face) + { + /* crStateStencilFuncPerform accepts 0 value, while glStencilFuncSeparate does not, + * filter it out here */ + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilFuncSeparate"); + return; + } + crStateStencilFuncPerform(face, func, ref, mask); } -void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass) +void STATE_APIENTRY crStateStencilFunc(GLenum func, GLint ref, GLuint mask) +{ + crStateStencilFuncPerform(0, func, ref, mask); +} + +static void STATE_APIENTRY crStateStencilBufferOp (CRContext *g, CRStencilBufferState *s, GLenum fail, GLenum zfail, GLenum zpass) +{ + s->fail = fail; + s->passDepthFail = zfail; + s->passDepthPass = zpass; +} + +static void crStateStencilOpPerform (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) { CRContext *g = GetCurrentContext(); CRStencilState *s = &(g->stencil); CRStateBits *stateb = GetCurrentBits(); CRStencilBits *sb = &(stateb->stencil); + GLint idx, bitsIdx, count, i; if (g->current.inBeginEnd) { @@ -146,14 +244,36 @@ void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass) return; } - s->fail = fail; - s->passDepthFail = zfail; - s->passDepthPass = zpass; + count = crStateStencilBufferGetIdxAndCount(s, face, &idx, &bitsIdx); + if (count) + { + for (i = idx; i < idx + count; ++i) + { + crStateStencilBufferOp(g, &s->buffers[i], fail, zfail, zpass); + } - DIRTY(sb->op, g->neg_bitid); - DIRTY(sb->dirty, g->neg_bitid); + DIRTY(sb->bufferRefs[bitsIdx].op, g->neg_bitid); + + DIRTY(sb->dirty, g->neg_bitid); + } } +void STATE_APIENTRY crStateStencilOpSeparate (GLenum face, GLenum fail, GLenum zfail, GLenum zpass) +{ + if (!face) + { + /* crStateStencilOpPerform accepts 0 value, while glStencilOpSeparate does not, + * filter it out here */ + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateStencilOpSeparate"); + return; + } + crStateStencilOpPerform (0, fail, zfail, zpass); +} + +void STATE_APIENTRY crStateStencilOp (GLenum fail, GLenum zfail, GLenum zpass) +{ + crStateStencilOpPerform (0, fail, zfail, zpass); +} void STATE_APIENTRY crStateClearStencil (GLint c) { @@ -171,7 +291,6 @@ void STATE_APIENTRY crStateClearStencil (GLint c) FLUSH(); - s->clearValue = c; DIRTY(sb->clearValue, g->neg_bitid); @@ -199,3 +318,1129 @@ void STATE_APIENTRY crStateStencilMask (GLuint mask) DIRTY(sb->writeMask, g->neg_bitid); DIRTY(sb->dirty, g->neg_bitid); } + +void STATE_APIENTRY crStateActiveStencilFaceEXT (GLenum face) +{ + CRContext *g = GetCurrentContext(); + CRStencilState *s = &(g->stencil); + CRStateBits *stateb = GetCurrentBits(); + CRStencilBits *sb = &(stateb->stencil); + + switch (face) + { + case GL_FRONT: + case GL_BACK: + s->activeStencilFace = face; + break; + default: + crStateError(__LINE__,__FILE__,GL_INVALID_ENUM, "crStateActiveStencilFaceEXT"); + return; + } + + DIRTY(sb->activeStencilFace, g->neg_bitid); + DIRTY(sb->dirty, g->neg_bitid); +} + +#ifdef CRSTATE_DEBUG_STENCIL_ERR +#define CRSTATE_CLEARERR() do { \ + while (diff_api.GetError() != GL_NO_ERROR) {} \ + } while (0) + +#define CRSTATE_CHECKGLERR(_op) do {\ + GLenum _glErr; \ + CRSTATE_CLEARERR(); \ + _op; \ + while ((_glErr = diff_api.GetError()) != GL_NO_ERROR) { Assert(0);} \ + }while (0) +#else +#define CRSTATE_CHECKGLERR(_op) do { _op; } while (0) +#endif + +#define CR_STATE_STENCIL_FUNC_MATCH(_s1, _i1, _s2, _i2) (\ + (_s1)->buffers[(_i1)].func == (_s2)->buffers[(_i2)].func && \ + (_s1)->buffers[(_i1)].ref == (_s2)->buffers[(_i2)].ref && \ + (_s1)->buffers[(_i1)].mask == (_s2)->buffers[(_i2)].mask) + +#define CR_STATE_STENCIL_FUNC_COPY(_s1, _i1, _s2, _i2) do { \ + (_s1)->buffers[(_i1)].func = (_s2)->buffers[(_i2)].func; \ + (_s1)->buffers[(_i1)].ref = (_s2)->buffers[(_i2)].ref; \ + (_s1)->buffers[(_i1)].mask = (_s2)->buffers[(_i2)].mask; \ + } while (0) + + +#define CR_STATE_STENCIL_OP_MATCH(_s1, _i1, _s2, _i2) (\ + (_s1)->buffers[(_i1)].fail == (_s2)->buffers[(_i2)].fail && \ + (_s1)->buffers[(_i1)].passDepthFail == (_s2)->buffers[(_i2)].passDepthFail && \ + (_s1)->buffers[(_i1)].passDepthPass == (_s2)->buffers[(_i2)].passDepthPass) + +#define CR_STATE_STENCIL_OP_COPY(_s1, _i1, _s2, _i2) do { \ + (_s1)->buffers[(_i1)].fail = (_s2)->buffers[(_i2)].fail; \ + (_s1)->buffers[(_i1)].passDepthFail = (_s2)->buffers[(_i2)].passDepthFail; \ + (_s1)->buffers[(_i1)].passDepthPass = (_s2)->buffers[(_i2)].passDepthPass; \ + } while (0) + + +void crStateStencilDiff(CRStencilBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRStencilState *from = &(fromCtx->stencil); + CRStencilState *to = &(toCtx->stencil); + unsigned int j, i; + GLenum activeFace; + GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty; + GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + + if (CHECKDIRTY(b->enable, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTest != to->stencilTest) + { + able[to->stencilTest](GL_STENCIL_TEST); + from->stencilTest = to->stencilTest; + } + CLEARDIRTY(b->enable, nbitID); + } + + if (CHECKDIRTY(b->enableTwoSideEXT, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTwoSideEXT != to->stencilTwoSideEXT) + { + able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT); + from->stencilTwoSideEXT = to->stencilTwoSideEXT; + } + CLEARDIRTY(b->enableTwoSideEXT, nbitID); + } + + if (CHECKDIRTY(b->clearValue, bitID)) + { + if (from->clearValue != to->clearValue) + { + diff_api.ClearStencil (to->clearValue); + from->clearValue = to->clearValue; + } + CLEARDIRTY(b->clearValue, nbitID); + } + + activeFace = to->activeStencilFace; + + + /* func */ + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID); +#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH() + || !CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + + backIsSet = GL_TRUE; + } + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask); + + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID)) + { + if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + diff_api.ActiveStencilFaceEXT(GL_BACK); + activeFace = GL_BACK; + } + + diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask); + CR_STATE_STENCIL_FUNC_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID); + } + +#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH +#undef CR_STATE_STENCIL_FUNC_BACK_MATCH +#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH + + /* op */ + backIsSet = GL_FALSE, frontIsSet = GL_FALSE; + frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID); + +#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH() + || !CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass); + + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT); + + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK); + backIsSet = GL_TRUE; + } + } + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID)) + { + if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + diff_api.ActiveStencilFaceEXT(GL_BACK); + activeFace = GL_BACK; + } + + diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass); + CR_STATE_STENCIL_OP_COPY(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID); + } + +#undef CR_STATE_STENCIL_OP_FRONT_MATCH +#undef CR_STATE_STENCIL_OP_BACK_MATCH +#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH + + + if (activeFace != to->activeStencilFace) + { + diff_api.ActiveStencilFaceEXT(activeFace); + } + + if (CHECKDIRTY(b->activeStencilFace, bitID)) + { + if (from->activeStencilFace != to->activeStencilFace) + { + /* we already did it ( see above )*/ + /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */ + from->activeStencilFace = to->activeStencilFace; + } + CLEARDIRTY(b->activeStencilFace, nbitID); + } + + if (CHECKDIRTY(b->writeMask, bitID)) + { + if (from->writeMask != to->writeMask) + { + diff_api.StencilMask (to->writeMask); + from->writeMask = to->writeMask; + } + CLEARDIRTY(b->writeMask, nbitID); + } + CLEARDIRTY(b->dirty, nbitID); +} + +void crStateStencilSwitch(CRStencilBits *b, CRbitvalue *bitID, + CRContext *fromCtx, CRContext *toCtx) +{ + CRStencilState *from = &(fromCtx->stencil); + CRStencilState *to = &(toCtx->stencil); + unsigned int j, i; + GLenum activeFace; + GLboolean backIsSet = GL_FALSE, frontIsSet = GL_FALSE, frontBackDirty, frontDirty, backDirty; + GLchar frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + CRbitvalue nbitID[CR_MAX_BITARRAY]; + for (j=0;j<CR_MAX_BITARRAY;j++) + nbitID[j] = ~bitID[j]; + i = 0; /* silence compiler */ + + if (CHECKDIRTY(b->enable, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTest != to->stencilTest) + { + CRSTATE_CHECKGLERR(able[to->stencilTest](GL_STENCIL_TEST)); + FILLDIRTY(b->enable); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->enable, nbitID); + } + if (CHECKDIRTY(b->enableTwoSideEXT, bitID)) + { + glAble able[2]; + able[0] = diff_api.Disable; + able[1] = diff_api.Enable; + if (from->stencilTwoSideEXT != to->stencilTwoSideEXT) + { + CRSTATE_CHECKGLERR(able[to->stencilTwoSideEXT](GL_STENCIL_TEST_TWO_SIDE_EXT)); + FILLDIRTY(b->enableTwoSideEXT); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->enableTwoSideEXT, nbitID); + } + if (CHECKDIRTY(b->clearValue, bitID)) + { + if (from->clearValue != to->clearValue) + { + CRSTATE_CHECKGLERR(diff_api.ClearStencil (to->clearValue)); + FILLDIRTY(b->clearValue); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->clearValue, nbitID); + } + + activeFace = from->activeStencilFace; + + /* func */ + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, bitID); +#define CR_STATE_STENCIL_FUNC_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_FUNC_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_FUNC_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH() + || !CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask)); + backIsSet = GL_TRUE; + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func); + FILLDIRTY(b->dirty); + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].func, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask)); + backIsSet = GL_TRUE; + } + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].func, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_FUNC_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + diff_api.ActiveStencilFaceEXT(GL_FRONT); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFuncSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].mask)); + backIsSet = GL_TRUE; + } + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].func, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, bitID)) + { + if (!CR_STATE_STENCIL_FUNC_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK)); + activeFace = GL_BACK; + } + + CRSTATE_CHECKGLERR(diff_api.StencilFunc (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask)); + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].func, nbitID); + } + +#undef CR_STATE_STENCIL_FUNC_FRONT_MATCH +#undef CR_STATE_STENCIL_FUNC_BACK_MATCH +#undef CR_STATE_STENCIL_FUNC_TO_FRONT_BACK_MATCH + + /* op */ + backIsSet = GL_FALSE, frontIsSet = GL_FALSE; + frontMatch = -1, backMatch = -1, toFrontBackMatch = -1; + frontBackDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, bitID); + frontDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, bitID); + backDirty = CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, bitID); + +#define CR_STATE_STENCIL_OP_FRONT_MATCH() ( \ + frontMatch >= 0 ? \ + frontMatch \ + : (frontMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_FRONT))) + +#define CR_STATE_STENCIL_OP_BACK_MATCH() ( \ + backMatch >= 0 ? \ + backMatch \ + : (backMatch = CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_BACK, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + +#define CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH() ( \ + toFrontBackMatch >= 0 ? \ + toFrontBackMatch \ + : (toFrontBackMatch = CR_STATE_STENCIL_OP_MATCH(to, CRSTATE_STENCIL_BUFFER_ID_FRONT, to, CRSTATE_STENCIL_BUFFER_ID_BACK))) + + if (frontBackDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH() + || !CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + frontIsSet = GL_TRUE; + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass)); + backIsSet = GL_TRUE; + } + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op); + FILLDIRTY(b->dirty); + } + + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT_AND_BACK].op, nbitID); + } + + if (frontDirty) + { + if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass)); + backIsSet = GL_TRUE; + } + } + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_FRONT].op, nbitID); + } + + + if (backDirty) + { + if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH()) + { + if (!frontIsSet || !backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + + frontIsSet = GL_TRUE; + backIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_FRONT_MATCH()) + { + if (!frontIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_FRONT, to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass)); + frontIsSet = GL_TRUE; + } + } + else if (!CR_STATE_STENCIL_OP_BACK_MATCH()) + { + if (!backIsSet) + { + if (activeFace == GL_BACK) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_FRONT)); + activeFace = GL_FRONT; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOpSeparate (GL_BACK, to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK].passDepthPass)); + backIsSet = GL_TRUE; + } + } + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_BACK].op, nbitID); + } + + if (CHECKDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, bitID)) + { + if (!CR_STATE_STENCIL_OP_MATCH(from, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK, to, CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK)) + { + if (activeFace == GL_FRONT) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(GL_BACK)); + activeFace = GL_BACK; + } + + CRSTATE_CHECKGLERR(diff_api.StencilOp (to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail, + to->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass)); + + FILLDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->bufferRefs[CRSTATE_STENCIL_BUFFER_REF_ID_TWO_SIDE_BACK].op, nbitID); + } + +#undef CR_STATE_STENCIL_OP_FRONT_MATCH +#undef CR_STATE_STENCIL_OP_BACK_MATCH +#undef CR_STATE_STENCIL_OP_TO_FRONT_BACK_MATCH + + if (activeFace != to->activeStencilFace) + { + CRSTATE_CHECKGLERR(diff_api.ActiveStencilFaceEXT(activeFace)); + } + + if (CHECKDIRTY(b->activeStencilFace, bitID)) + { + if (from->activeStencilFace != to->activeStencilFace) + { + /* we already did it ( see above )*/ + /* diff_api.ActiveStencilFaceEXT(to->activeStencilFace); */ + FILLDIRTY(b->activeStencilFace); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->activeStencilFace, nbitID); + } + + if (CHECKDIRTY(b->writeMask, bitID)) + { + if (from->writeMask != to->writeMask) + { + CRSTATE_CHECKGLERR(diff_api.StencilMask (to->writeMask)); + FILLDIRTY(b->writeMask); + FILLDIRTY(b->dirty); + } + CLEARDIRTY(b->writeMask, nbitID); + } + + CLEARDIRTY(b->dirty, nbitID); +} + |
