stencil.c
来自「Mesa is an open-source implementation of」· C语言 代码 · 共 561 行 · 第 1/2 页
C
561 行
if (ctx->Driver.StencilMaskSeparate) { ctx->Driver.StencilMaskSeparate(ctx, GL_FRONT_AND_BACK, mask); } }}/** * Set the stencil test actions. * * \param fail action to take when stencil test fails. * \param zfail action to take when stencil test passes, but depth test fails. * \param zpass action to take when stencil test passes and the depth test * passes (or depth testing is not enabled). * * \sa glStencilOp(). * * Verifies the parameters and updates the respective fields in * __GLcontextRec::Stencil. On change flushes the vertices and notifies the * driver via the dd_function_table::StencilOp callback. */void GLAPIENTRY_mesa_StencilOp(GLenum fail, GLenum zfail, GLenum zpass){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (!validate_stencil_op(ctx, fail)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(sfail)"); return; } if (!validate_stencil_op(ctx, zfail)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zfail)"); return; } if (!validate_stencil_op(ctx, zpass)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOp(zpass)"); return; } if (ctx->Extensions.EXT_stencil_two_side) { /* only set active face state */ const GLint face = ctx->Stencil.ActiveFace; if (ctx->Stencil.ZFailFunc[face] == zfail && ctx->Stencil.ZPassFunc[face] == zpass && ctx->Stencil.FailFunc[face] == fail) return; FLUSH_VERTICES(ctx, _NEW_STENCIL); ctx->Stencil.ZFailFunc[face] = zfail; ctx->Stencil.ZPassFunc[face] = zpass; ctx->Stencil.FailFunc[face] = fail; if (ctx->Driver.StencilOpSeparate) { ctx->Driver.StencilOpSeparate(ctx, face ? GL_BACK : GL_FRONT, fail, zfail, zpass); } } else { /* set both front and back state */ if (ctx->Stencil.ZFailFunc[0] == zfail && ctx->Stencil.ZFailFunc[1] == zfail && ctx->Stencil.ZPassFunc[0] == zpass && ctx->Stencil.ZPassFunc[1] == zpass && ctx->Stencil.FailFunc[0] == fail && ctx->Stencil.FailFunc[1] == fail) return; FLUSH_VERTICES(ctx, _NEW_STENCIL); ctx->Stencil.ZFailFunc[0] = ctx->Stencil.ZFailFunc[1] = zfail; ctx->Stencil.ZPassFunc[0] = ctx->Stencil.ZPassFunc[1] = zpass; ctx->Stencil.FailFunc[0] = ctx->Stencil.FailFunc[1] = fail; if (ctx->Driver.StencilOpSeparate) { ctx->Driver.StencilOpSeparate(ctx, GL_FRONT_AND_BACK, fail, zfail, zpass); } }}#if _HAVE_FULL_GL/* GL_EXT_stencil_two_side */void GLAPIENTRY_mesa_ActiveStencilFaceEXT(GLenum face){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (!ctx->Extensions.EXT_stencil_two_side) { _mesa_error(ctx, GL_INVALID_OPERATION, "glActiveStencilFaceEXT"); return; } if (face == GL_FRONT || face == GL_BACK) { FLUSH_VERTICES(ctx, _NEW_STENCIL); ctx->Stencil.ActiveFace = (face == GL_FRONT) ? 0 : 1; } else { _mesa_error(ctx, GL_INVALID_ENUM, "glActiveStencilFaceEXT(face)"); }}#endif/** * OpenGL 2.0 function. * \todo Make StencilOp() call this function. And eventually remove the * ctx->Driver.StencilOp function and use ctx->Driver.StencilOpSeparate * instead. */void GLAPIENTRY_mesa_StencilOpSeparate(GLenum face, GLenum sfail, GLenum zfail, GLenum zpass){ GLboolean set = GL_FALSE; GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (!validate_stencil_op(ctx, sfail)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(sfail)"); return; } if (!validate_stencil_op(ctx, zfail)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zfail)"); return; } if (!validate_stencil_op(ctx, zpass)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(zpass)"); return; } if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilOpSeparate(face)"); return; } if (face != GL_BACK) { /* set front */ if (ctx->Stencil.ZFailFunc[0] != zfail || ctx->Stencil.ZPassFunc[0] != zpass || ctx->Stencil.FailFunc[0] != sfail){ FLUSH_VERTICES(ctx, _NEW_STENCIL); ctx->Stencil.ZFailFunc[0] = zfail; ctx->Stencil.ZPassFunc[0] = zpass; ctx->Stencil.FailFunc[0] = sfail; set = GL_TRUE; } } if (face != GL_FRONT) { /* set back */ if (ctx->Stencil.ZFailFunc[1] != zfail || ctx->Stencil.ZPassFunc[1] != zpass || ctx->Stencil.FailFunc[1] != sfail) { FLUSH_VERTICES(ctx, _NEW_STENCIL); ctx->Stencil.ZFailFunc[1] = zfail; ctx->Stencil.ZPassFunc[1] = zpass; ctx->Stencil.FailFunc[1] = sfail; set = GL_TRUE; } } if (set && ctx->Driver.StencilOpSeparate) { ctx->Driver.StencilOpSeparate(ctx, face, sfail, zfail, zpass); }}/* OpenGL 2.0 */void GLAPIENTRY_mesa_StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask){ GET_CURRENT_CONTEXT(ctx); const GLint stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1; ASSERT_OUTSIDE_BEGIN_END(ctx); if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(face)"); return; } if (!validate_stencil_func(ctx, func)) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilFuncSeparate(func)"); return; } ref = CLAMP(ref, 0, stencilMax); FLUSH_VERTICES(ctx, _NEW_STENCIL); if (face != GL_BACK) { /* set front */ ctx->Stencil.Function[0] = func; ctx->Stencil.Ref[0] = ref; ctx->Stencil.ValueMask[0] = mask; } if (face != GL_FRONT) { /* set back */ ctx->Stencil.Function[1] = func; ctx->Stencil.Ref[1] = ref; ctx->Stencil.ValueMask[1] = mask; } if (ctx->Driver.StencilFuncSeparate) { ctx->Driver.StencilFuncSeparate(ctx, face, func, ref, mask); }}/* OpenGL 2.0 */void GLAPIENTRY_mesa_StencilMaskSeparate(GLenum face, GLuint mask){ GET_CURRENT_CONTEXT(ctx); ASSERT_OUTSIDE_BEGIN_END(ctx); if (face != GL_FRONT && face != GL_BACK && face != GL_FRONT_AND_BACK) { _mesa_error(ctx, GL_INVALID_ENUM, "glStencilaMaskSeparate(face)"); return; } FLUSH_VERTICES(ctx, _NEW_STENCIL); if (face != GL_BACK) { ctx->Stencil.WriteMask[0] = mask; } if (face != GL_FRONT) { ctx->Stencil.WriteMask[1] = mask; } if (ctx->Driver.StencilMaskSeparate) { ctx->Driver.StencilMaskSeparate(ctx, face, mask); }}/** * Update derived stencil state. */void_mesa_update_stencil(GLcontext *ctx){ if (ctx->Extensions.EXT_stencil_two_side) { ctx->Stencil._TestTwoSide = ctx->Stencil.TestTwoSide; } else { ctx->Stencil._TestTwoSide = (ctx->Stencil.Function[0] != ctx->Stencil.Function[1] || ctx->Stencil.FailFunc[0] != ctx->Stencil.FailFunc[1] || ctx->Stencil.ZPassFunc[0] != ctx->Stencil.ZPassFunc[1] || ctx->Stencil.ZFailFunc[0] != ctx->Stencil.ZFailFunc[1] || ctx->Stencil.Ref[0] != ctx->Stencil.Ref[1] || ctx->Stencil.ValueMask[0] != ctx->Stencil.ValueMask[1] || ctx->Stencil.WriteMask[0] != ctx->Stencil.WriteMask[1]); }}/** * Initialize the context stipple state. * * \param ctx GL context. * * Initializes __GLcontextRec::Stencil attribute group. */void_mesa_init_stencil(GLcontext *ctx){ ctx->Stencil.Enabled = GL_FALSE; ctx->Stencil.TestTwoSide = GL_FALSE; ctx->Stencil.ActiveFace = 0; /* 0 = GL_FRONT, 1 = GL_BACK */ ctx->Stencil.Function[0] = GL_ALWAYS; ctx->Stencil.Function[1] = GL_ALWAYS; ctx->Stencil.FailFunc[0] = GL_KEEP; ctx->Stencil.FailFunc[1] = GL_KEEP; ctx->Stencil.ZPassFunc[0] = GL_KEEP; ctx->Stencil.ZPassFunc[1] = GL_KEEP; ctx->Stencil.ZFailFunc[0] = GL_KEEP; ctx->Stencil.ZFailFunc[1] = GL_KEEP; ctx->Stencil.Ref[0] = 0; ctx->Stencil.Ref[1] = 0; ctx->Stencil.ValueMask[0] = ~0U; ctx->Stencil.ValueMask[1] = ~0U; ctx->Stencil.WriteMask[0] = ~0U; ctx->Stencil.WriteMask[1] = ~0U; ctx->Stencil.Clear = 0;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?