|
|
/*
** Copyright 1991, 1992, 1993, Silicon Graphics, Inc. ** All Rights Reserved. ** ** This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.; ** the contents of this file may not be disclosed to third parties, copied or ** duplicated in any form, in whole or in part, without the prior written ** permission of Silicon Graphics, Inc. ** ** RESTRICTED RIGHTS LEGEND: ** Use, duplication or disclosure by the Government is subject to restrictions ** as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data ** and Computer Software clause at DFARS 252.227-7013, and/or in similar or ** successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished - ** rights reserved under the Copyright Laws of the United States. */ #include "precomp.h"
#pragma hdrstop
GLint FASTCALL Fetch(__GLstencilBuffer *sfb, GLint x, GLint y) { __GLstencilCell *fb;
fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y); return fb[0]; }
static void Store(__GLstencilBuffer *sfb, GLint x, GLint y,GLint v) { __GLstencilCell *fb;
fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y); fb[0] = (__GLstencilCell) ((v & sfb->buf.gc->state.stencil.writeMask) | (fb[0] & ~sfb->buf.gc->state.stencil.writeMask)); }
static GLboolean FASTCALL TestFunc(__GLstencilBuffer *sfb, GLint x, GLint y) { __GLstencilCell *fb;
fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y); return sfb->testFuncTable[fb[0] & sfb->buf.gc->state.stencil.mask]; }
static void FASTCALL FailOp(__GLstencilBuffer *sfb, GLint x, GLint y) { __GLstencilCell *fb;
fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y); fb[0] = sfb->failOpTable[fb[0]]; }
static void FASTCALL PassDepthFailOp(__GLstencilBuffer *sfb, GLint x, GLint y) { __GLstencilCell *fb;
fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y); fb[0] = sfb->depthFailOpTable[fb[0]]; }
static void FASTCALL DepthPassOp(__GLstencilBuffer *sfb, GLint x, GLint y) { __GLstencilCell *fb;
fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y); fb[0] = sfb->depthPassOpTable[fb[0]]; }
static GLboolean FASTCALL NoOp(__GLstencilBuffer *sfb, GLint x, GLint y) { return GL_FALSE; }
/************************************************************************/
static void FASTCALL Clear(__GLstencilBuffer *sfb) { __GLcontext *gc = sfb->buf.gc; __GLstencilCell *fb; GLint x, y, x1, y1, skip, w, w8, w1; __GLstencilCell sten = (__GLstencilCell)gc->state.stencil.clear;
x = gc->transform.clipX0; y = gc->transform.clipY0; x1 = gc->transform.clipX1; y1 = gc->transform.clipY1; if (((w = x1 - x) == 0) || (y1 - y == 0)) { return; }
fb = __GL_STENCIL_ADDR(sfb, (__GLstencilCell*), x, y);
skip = sfb->buf.outerWidth - w; w8 = w >> 3; w1 = w & 7; if (gc->state.stencil.writeMask == __GL_MAX_STENCIL_VALUE) { for (; y < y1; y++) { w = w8; while (--w >= 0) { fb[0] = sten; fb[1] = sten; fb[2] = sten; fb[3] = sten; fb[4] = sten; fb[5] = sten; fb[6] = sten; fb[7] = sten; fb += 8; } w = w1; while (--w >= 0) { *fb++ = sten; } fb += skip; } } else { GLint mask;
mask = gc->state.stencil.writeMask; sten = sten & mask; mask = ~mask;
for (; y < y1; y++) { w = w8; while (--w >= 0) { fb[0] = (fb[0] & mask) | (sten); fb[1] = (fb[1] & mask) | (sten); fb[2] = (fb[2] & mask) | (sten); fb[3] = (fb[3] & mask) | (sten); fb[4] = (fb[4] & mask) | (sten); fb[5] = (fb[5] & mask) | (sten); fb[6] = (fb[6] & mask) | (sten); fb[7] = (fb[7] & mask) | (sten); fb += 8; } w = w1; while (--w >= 0) { fb[0] = (fb[0] & mask) | (sten); fb++; } fb += skip; } } }
/************************************************************************/
static void buildOpTable(__GLstencilCell *tp, GLenum op, __GLstencilCell reference, __GLstencilCell writeMask) { GLuint i; __GLstencilCell newValue; __GLstencilCell notWriteMask = ~writeMask;
for (i = 0; i < __GL_STENCIL_RANGE; i++) { switch (op) { case GL_KEEP: newValue = (__GLstencilCell)i; break; case GL_ZERO: newValue = 0; break; case GL_REPLACE: newValue = reference; break; case GL_INVERT: newValue = ~i; break; case GL_INCR: /* Clamp so no overflow occurs */ if (i == __GL_MAX_STENCIL_VALUE) { newValue = (__GLstencilCell)i; } else { newValue = i + 1; } break; case GL_DECR: /* Clamp so no underflow occurs */ if (i == 0) { newValue = 0; } else { newValue = i - 1; } break; } *tp++ = (i & notWriteMask) | (newValue & writeMask); } }
#ifdef NT
void FASTCALL __glValidateStencil(__GLcontext *gc, __GLstencilBuffer *sfb) #else
void FASTCALL __glValidateStencil(__GLcontext *gc) #endif // NT
{ GLint i; __GLstencilCell reference, mask, writeMask; __GLstencilCell refVal; //actual reference value, part of GL state
GLenum testFunc; GLboolean *tp;
/*
** Validate the stencil tables even if stenciling is disabled. This ** function is only called if the stencil func or op changes, and it ** won't get called later if stenciling is turned on, so we need to get ** it right now. */
mask = (__GLstencilCell) gc->state.stencil.mask; refVal = ((__GLstencilCell) gc->state.stencil.reference); reference = (__GLstencilCell) (refVal & mask); testFunc = gc->state.stencil.testFunc;
/*
** Build up test function table. The current stencil buffer value ** will be the index to this table. */ tp = &gc->stencilBuffer.testFuncTable[0]; // If we don't have a stencil buffer then set everything to
// do nothing
if (!gc->modes.haveStencilBuffer) { sfb->testFunc = NoOp; sfb->failOp = NoOp; sfb->passDepthFailOp = NoOp; sfb->depthPassOp = NoOp; return; } else if (tp != NULL && sfb->testFunc == NoOp) { // If we've recovered from not having a stencil buffer then
// turn the functions back on
sfb->testFunc = TestFunc; sfb->failOp = FailOp; sfb->passDepthFailOp = PassDepthFailOp; sfb->depthPassOp = DepthPassOp; }
if (!tp) { gc->stencilBuffer.testFuncTable = tp = (GLboolean *) GCALLOC(gc, (sizeof(GLboolean)+3*sizeof(__GLstencilCell))* __GL_STENCIL_RANGE); if (!tp) { sfb->testFunc = NoOp; sfb->failOp = NoOp; sfb->passDepthFailOp = NoOp; sfb->depthPassOp = NoOp; gc->stencilBuffer.failOpTable = gc->stencilBuffer.depthFailOpTable = gc->stencilBuffer.depthPassOpTable = (__GLstencilCell*) NULL; return; } else { sfb->testFunc = TestFunc; sfb->failOp = FailOp; sfb->passDepthFailOp = PassDepthFailOp; sfb->depthPassOp = DepthPassOp; } gc->stencilBuffer.failOpTable = (__GLstencilCell*) (gc->stencilBuffer.testFuncTable + __GL_STENCIL_RANGE); gc->stencilBuffer.depthFailOpTable = (__GLstencilCell*) (gc->stencilBuffer.failOpTable + __GL_STENCIL_RANGE); gc->stencilBuffer.depthPassOpTable = (__GLstencilCell*) (gc->stencilBuffer.depthFailOpTable + __GL_STENCIL_RANGE); } for (i = 0; i < __GL_STENCIL_RANGE; i++) { switch (testFunc) { case GL_NEVER: *tp++ = GL_FALSE; break; case GL_LESS: *tp++ = reference < (i & mask); break; case GL_EQUAL: *tp++ = reference == (i & mask); break; case GL_LEQUAL: *tp++ = reference <= (i & mask); break; case GL_GREATER: *tp++ = reference > (i & mask); break; case GL_NOTEQUAL: *tp++ = reference != (i & mask); break; case GL_GEQUAL: *tp++ = reference >= (i & mask); break; case GL_ALWAYS: *tp++ = GL_TRUE; break; } }
/*
** Build up fail op table. */ writeMask = (__GLstencilCell) gc->state.stencil.writeMask; buildOpTable(&gc->stencilBuffer.failOpTable[0], gc->state.stencil.fail, refVal, writeMask); buildOpTable(&gc->stencilBuffer.depthFailOpTable[0], gc->state.stencil.depthFail, refVal, writeMask); buildOpTable(&gc->stencilBuffer.depthPassOpTable[0], gc->state.stencil.depthPass, refVal, writeMask); }
/************************************************************************/
static void FASTCALL Pick(__GLcontext *gc, __GLstencilBuffer *sfb) { #ifdef __GL_LINT
sfb = sfb; #endif
if (gc->validateMask & (__GL_VALIDATE_STENCIL_FUNC | __GL_VALIDATE_STENCIL_OP)) { #ifdef NT
__glValidateStencil(gc, sfb); #else
__glValidateStencil(gc); #endif // NT
} }
void FASTCALL __glInitStencil8(__GLcontext *gc, __GLstencilBuffer *sfb) { sfb->buf.elementSize = sizeof(__GLstencilCell); sfb->buf.gc = gc; sfb->pick = Pick; sfb->store = Store; sfb->fetch = Fetch; #ifndef NT
// Initialized in __glValidateStencil.
sfb->testFunc = TestFunc; sfb->failOp = FailOp; sfb->passDepthFailOp = PassDepthFailOp; sfb->depthPassOp = DepthPassOp; #endif // !NT
sfb->clear = Clear; }
void FASTCALL __glFreeStencil8(__GLcontext *gc, __GLstencilBuffer *fb) { #ifdef __GL_LINT
gc = gc; fb = fb; #endif
}
|