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

📄 s_stencil.c

📁 mesa-6.5-minigui源码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Mesa 3-D graphics library * Version:  6.5 * * Copyright (C) 1999-2005  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;}/** * 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 *         z - array [n] of z values *         mask - array [n] of flags  (1=test this pixel, 0=skip the pixel) * Output:  mask - array [n] of flags (1=stencil and depth test passed) * Return: GL_FALSE - all fragments failed the testing *         GL_TRUE - one or more fragments passed the testing * */static GLbooleanstencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face){   struct gl_framebuffer *fb = ctx->DrawBuffer;   struct gl_renderbuffer *rb = fb->_StencilBuffer;   GLstencil stencilRow[MAX_WIDTH];   GLstencil *stencil;   const GLuint n = span->end;   const GLint x = span->x;   const GLint y = span->y;   GLubyte *mask = span->array->mask;   ASSERT((span->arrayMask & SPAN_XY) == 0);   ASSERT(ctx->Stencil.Enabled);

⌨️ 快捷键说明

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