⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s_stencil.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Mesa 3-D graphics library * Version:  7.1 * * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */#include "glheader.h"#include "context.h"#include "imports.h"#include "s_context.h"#include "s_depth.h"#include "s_stencil.h"#include "s_span.h"/* Stencil Logic:IF stencil test fails THEN   Apply fail-op to stencil value   Don't write the pixel (RGBA,Z)ELSE   IF doing depth test && depth test fails THEN      Apply zfail-op to stencil value      Write RGBA and Z to appropriate buffers   ELSE      Apply zpass-op to stencil valueENDIF*//** * Apply the given stencil operator to the array of stencil values. * Don't touch stencil[i] if mask[i] is zero. * Input:  n - size of stencil array *         oper - the stencil buffer operator *         face - 0 or 1 for front or back face operation *         stencil - array of stencil values *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator * Output:  stencil - modified values */static voidapply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face,                  GLuint n, GLstencil stencil[], const GLubyte mask[] ){   const GLstencil ref = ctx->Stencil.Ref[face];   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];   const GLstencil invmask = (GLstencil) (~wrtmask);   const GLstencil stencilMax = (1 << ctx->DrawBuffer->Visual.stencilBits) - 1;   GLuint i;   switch (oper) {      case GL_KEEP:         /* do nothing */         break;      case GL_ZERO:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  stencil[i] = 0;	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  stencil[i] = (GLstencil) (stencil[i] & invmask);	       }	    }	 }	 break;      case GL_REPLACE:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  stencil[i] = ref;	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  GLstencil s = stencil[i];		  stencil[i] = (GLstencil) ((invmask & s ) | (wrtmask & ref));	       }	    }	 }	 break;      case GL_INCR:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  GLstencil s = stencil[i];		  if (s < stencilMax) {		     stencil[i] = (GLstencil) (s+1);		  }	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  /* VERIFY logic of adding 1 to a write-masked value */		  GLstencil s = stencil[i];		  if (s < stencilMax) {		     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));		  }	       }	    }	 }	 break;      case GL_DECR:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  GLstencil s = stencil[i];		  if (s>0) {		     stencil[i] = (GLstencil) (s-1);		  }	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  /* VERIFY logic of subtracting 1 to a write-masked value */		  GLstencil s = stencil[i];		  if (s>0) {		     stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));		  }	       }	    }	 }	 break;      case GL_INCR_WRAP_EXT:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  stencil[i]++;	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil s = stencil[i];                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s+1)));	       }	    }	 }	 break;      case GL_DECR_WRAP_EXT:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  stencil[i]--;	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil s = stencil[i];                  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & (s-1)));	       }	    }	 }	 break;      case GL_INVERT:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  GLstencil s = stencil[i];		  stencil[i] = (GLstencil) ~s;	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {		  GLstencil s = stencil[i];		  stencil[i] = (GLstencil) ((invmask & s) | (wrtmask & ~s));	       }	    }	 }	 break;      default:         _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");   }}/** * Apply stencil test to an array of stencil values (before depth buffering). * Input:  face - 0 or 1 for front or back-face polygons *         n - number of pixels in the array *         stencil - array of [n] stencil values *         mask - array [n] of flag:  0=skip the pixel, 1=stencil the pixel * Output:  mask - pixels which fail the stencil test will have their *                 mask flag set to 0. *          stencil - updated stencil values (where the test passed) * Return:  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. */static GLbooleando_stencil_test( GLcontext *ctx, GLuint face, GLuint n, GLstencil stencil[],                 GLubyte mask[] ){   GLubyte fail[MAX_WIDTH];   GLboolean allfail = GL_FALSE;   GLuint i;   GLstencil r, s;   const GLuint valueMask = ctx->Stencil.ValueMask[face];   ASSERT(n <= MAX_WIDTH);   /*    * Perform stencil test.  The results of this operation are stored    * in the fail[] array:    *   IF fail[i] is non-zero THEN    *       the stencil fail operator is to be applied    *   ELSE    *       the stencil fail operator is not to be applied    *   ENDIF    */   switch (ctx->Stencil.Function[face]) {      case GL_NEVER:         /* never pass; always fail */         for (i=0;i<n;i++) {	    if (mask[i]) {	       mask[i] = 0;	       fail[i] = 1;	    }	    else {	       fail[i] = 0;	    }	 }	 allfail = GL_TRUE;	 break;      case GL_LESS:	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);	 for (i=0;i<n;i++) {	    if (mask[i]) {	       s = (GLstencil) (stencil[i] & valueMask);	       if (r < s) {		  /* passed */		  fail[i] = 0;	       }	       else {		  fail[i] = 1;		  mask[i] = 0;	       }	    }	    else {	       fail[i] = 0;	    }	 }	 break;      case GL_LEQUAL:	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);	 for (i=0;i<n;i++) {	    if (mask[i]) {	       s = (GLstencil) (stencil[i] & valueMask);	       if (r <= s) {		  /* pass */		  fail[i] = 0;	       }	       else {		  fail[i] = 1;		  mask[i] = 0;	       }	    }	    else {	       fail[i] = 0;	    }	 }	 break;      case GL_GREATER:	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);	 for (i=0;i<n;i++) {	    if (mask[i]) {	       s = (GLstencil) (stencil[i] & valueMask);	       if (r > s) {		  /* passed */		  fail[i] = 0;	       }	       else {		  fail[i] = 1;		  mask[i] = 0;	       }	    }	    else {	       fail[i] = 0;	    }	 }	 break;      case GL_GEQUAL:	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);	 for (i=0;i<n;i++) {	    if (mask[i]) {	       s = (GLstencil) (stencil[i] & valueMask);	       if (r >= s) {		  /* passed */		  fail[i] = 0;	       }	       else {		  fail[i] = 1;		  mask[i] = 0;	       }	    }	    else {	       fail[i] = 0;	    }	 }	 break;      case GL_EQUAL:	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);	 for (i=0;i<n;i++) {	    if (mask[i]) {	       s = (GLstencil) (stencil[i] & valueMask);	       if (r == s) {		  /* passed */		  fail[i] = 0;	       }	       else {		  fail[i] = 1;		  mask[i] = 0;	       }	    }	    else {	       fail[i] = 0;	    }	 }	 break;      case GL_NOTEQUAL:	 r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask);	 for (i=0;i<n;i++) {	    if (mask[i]) {	       s = (GLstencil) (stencil[i] & valueMask);	       if (r != s) {		  /* passed */		  fail[i] = 0;	       }	       else {		  fail[i] = 1;		  mask[i] = 0;	       }	    }	    else {	       fail[i] = 0;	    }	 }	 break;      case GL_ALWAYS:	 /* always pass */	 for (i=0;i<n;i++) {	    fail[i] = 0;	 }	 break;      default:         _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");         return 0;   }   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {      apply_stencil_op( ctx, ctx->Stencil.FailFunc[face], face, n, stencil, fail );   }   return !allfail;}/** * Compute the zpass/zfail masks by comparing the pre- and post-depth test * masks. */static INLINE voidcompute_pass_fail_masks(GLuint n, const GLubyte origMask[],                        const GLubyte newMask[],                        GLubyte passMask[], GLubyte failMask[]){   GLuint i;   for (i = 0; i < n; i++) {      ASSERT(newMask[i] == 0 || newMask[i] == 1);      passMask[i] = origMask[i] & newMask[i];      failMask[i] = origMask[i] & (newMask[i] ^ 1);   }}/** * Apply stencil and depth testing to the span of pixels. * Both software and hardware stencil buffers are acceptable. * Input:  n - number of pixels in the span *         x, y - location of leftmost pixel in span

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -