/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include <stdio.h>
#include "state.h"
#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->stencilTwoSideEXT = GL_FALSE;
RESET(sb->enableTwoSideEXT, ctx->bitid);
s->activeStencilFace = GL_FRONT;
RESET(sb->activeStencilFace, ctx->bitid);
s->clearValue = 0;
RESET(sb->clearValue, ctx->bitid);
s->writeMask = 0xFFFFFFFF;
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]);
}
}
static void crStateStencilBufferFunc(CRContext *g, CRStencilBufferState *s, GLenum func, GLint ref, GLuint mask)
{
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 (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;
}
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 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)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"glStencilOp called in begin/end");
return;
}
FLUSH();
switch (fail) {
case GL_KEEP:
case GL_ZERO:
case GL_REPLACE:
case GL_INCR:
case GL_DECR:
case GL_INVERT:
#ifdef CR_EXT_stencil_wrap
case GL_INCR_WRAP_EXT:
case GL_DECR_WRAP_EXT:
#endif
break;
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
"glStencilOp called with bogus fail: %d", fail);
return;
}
switch (zfail) {
case GL_KEEP:
case GL_ZERO:
case GL_REPLACE:
case GL_INCR:
case GL_DECR:
case GL_INVERT:
#ifdef CR_EXT_stencil_wrap
case GL_INCR_WRAP_EXT:
case GL_DECR_WRAP_EXT:
#endif
break;
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
"glStencilOp called with bogus zfail: %d", zfail);
return;
}
switch (zpass) {
case GL_KEEP:
case GL_ZERO:
case GL_REPLACE:
case GL_INCR:
case GL_DECR:
case GL_INVERT:
#ifdef CR_EXT_stencil_wrap
case GL_INCR_WRAP_EXT:
case GL_DECR_WRAP_EXT:
#endif
break;
default:
crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
"glStencilOp called with bogus zpass: %d", zpass);
return;
}
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->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)
{
CRContext *g = GetCurrentContext();
CRStencilState *s = &(g->stencil);
CRStateBits *stateb = GetCurrentBits();
CRStencilBits *sb = &(stateb->stencil);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"glClearStencil called in begin/end");
return;
}
FLUSH();
s->clearValue = c;
DIRTY(sb->clearValue, g->neg_bitid);
DIRTY(sb->dirty, g->neg_bitid);
}
void STATE_APIENTRY crStateStencilMask (GLuint mask)
{
CRContext *g = GetCurrentContext();
CRStencilState *s = &(g->stencil);
CRStateBits *stateb = GetCurrentBits();
CRStencilBits *sb = &(stateb->stencil);
if (g->current.inBeginEnd)
{
crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
"glStencilMask called in begin/end");
return;
}
FLUSH();
s->writeMask = 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);
}