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

📄 s_stencil.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
 *         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, SWspan *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);   ASSERT(n <= MAX_WIDTH);#ifdef DEBUG   if (ctx->Depth.Test) {      ASSERT(span->arrayMask & SPAN_Z);   }#endif   stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y);   if (!stencil) {      rb->GetRow(ctx, rb, n, x, y, stencilRow);      stencil = stencilRow;   }   /*    * Apply the stencil test to the fragments.    * failMask[i] is 1 if the stencil test failed.    */   if (do_stencil_test( ctx, face, n, stencil, mask ) == GL_FALSE) {      /* all fragments failed the stencil test, we're done. */      span->writeAll = GL_FALSE;      if (!rb->GetPointer(ctx, rb, 0, 0)) {         /* put updated stencil values into buffer */         rb->PutRow(ctx, rb, n, x, y, stencil, NULL);      }      return GL_FALSE;   }   /*    * Some fragments passed the stencil test, apply depth test to them    * and apply Zpass and Zfail stencil ops.    */   if (ctx->Depth.Test == GL_FALSE) {      /*       * No depth buffer, just apply zpass stencil function to active pixels.       */      apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face, n, stencil, mask );   }   else {      /*       * Perform depth buffering, then apply zpass or zfail stencil function.       */      GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];      /* save the current mask bits */      _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));      /* apply the depth test */      _swrast_depth_test_span(ctx, span);      compute_pass_fail_masks(n, origMask, mask, passMask, failMask);      /* apply the pass and fail operations */      if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {         apply_stencil_op( ctx, ctx->Stencil.ZFailFunc[face], face,                           n, stencil, failMask );      }      if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {         apply_stencil_op( ctx, ctx->Stencil.ZPassFunc[face], face,                           n, stencil, passMask );      }   }   /*    * Write updated stencil values back into hardware stencil buffer.    */   if (!rb->GetPointer(ctx, rb, 0, 0)) {      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);   }      span->writeAll = GL_FALSE;      return GL_TRUE;  /* one or more fragments passed both tests */}/* * Return the address of a stencil buffer value given the window coords: */#define STENCIL_ADDRESS(X, Y)  (stencilStart + (Y) * stride + (X))/** * Apply the given stencil operator for each pixel in the array whose * mask flag is set. * \note  This is for software stencil buffers only. * Input:  n - number of pixels in the span *         x, y - array of [n] pixels *         operator - the stencil buffer operator *         mask - array [n] of flag:  1=apply operator, 0=don't apply operator */static voidapply_stencil_op_to_pixels( GLcontext *ctx,                            GLuint n, const GLint x[], const GLint y[],                            GLenum oper, GLuint face, const GLubyte mask[] ){   struct gl_framebuffer *fb = ctx->DrawBuffer;   struct gl_renderbuffer *rb = fb->_StencilBuffer;   const GLstencil stencilMax = (1 << fb->Visual.stencilBits) - 1;   const GLstencil ref = ctx->Stencil.Ref[face];   const GLstencil wrtmask = ctx->Stencil.WriteMask[face];   const GLstencil invmask = (GLstencil) (~wrtmask);   GLuint i;   GLstencil *stencilStart = (GLubyte *) rb->Data;   const GLuint stride = rb->Width;   ASSERT(rb->GetPointer(ctx, rb, 0, 0));   ASSERT(sizeof(GLstencil) == 1);   switch (oper) {      case GL_KEEP:         /* do nothing */         break;      case GL_ZERO:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = 0;	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );		  *sptr = (GLstencil) (invmask & *sptr);	       }	    }	 }	 break;      case GL_REPLACE:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = ref;	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );		  *sptr = (GLstencil) ((invmask & *sptr ) | (wrtmask & ref));	       }	    }	 }	 break;      case GL_INCR:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );		  if (*sptr < stencilMax) {		     *sptr = (GLstencil) (*sptr + 1);		  }	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );		  if (*sptr < stencilMax) {		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));		  }	       }	    }	 }	 break;      case GL_DECR:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );		  if (*sptr>0) {		     *sptr = (GLstencil) (*sptr - 1);		  }	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );		  if (*sptr>0) {		     *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));		  }	       }	    }	 }	 break;      case GL_INCR_WRAP_EXT:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = (GLstencil) (*sptr + 1);	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr+1)));	       }	    }	 }	 break;      case GL_DECR_WRAP_EXT:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = (GLstencil) (*sptr - 1);	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & (*sptr-1)));	       }	    }	 }	 break;      case GL_INVERT:	 if (invmask==0) {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = (GLstencil) (~*sptr);	       }	    }	 }	 else {	    for (i=0;i<n;i++) {	       if (mask[i]) {                  GLstencil *sptr = STENCIL_ADDRESS( x[i], y[i] );                  *sptr = (GLstencil) ((invmask & *sptr) | (wrtmask & ~*sptr));	       }	    }	 }	 break;      default:         _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");   }}/** * Apply stencil test to an array of pixels before depth buffering. * * \note Used for software stencil buffer only. * Input:  n - number of pixels in the span *         x, y - array of [n] pixels to stencil *         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. * \return  GL_FALSE = all pixels failed, GL_TRUE = zero or more pixels passed. */static GLbooleanstencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n,                     const GLint x[], const GLint y[], GLubyte mask[] ){   const struct gl_framebuffer *fb = ctx->DrawBuffer;   struct gl_renderbuffer *rb = fb->_StencilBuffer;   GLubyte fail[MAX_WIDTH];   GLstencil r, s;   GLuint i;   GLboolean allfail = GL_FALSE;   const GLuint valueMask = ctx->Stencil.ValueMask[face];   const GLstencil *stencilStart = (GLstencil *) rb->Data;   const GLuint stride = rb->Width;   ASSERT(rb->GetPointer(ctx, rb, 0, 0));   ASSERT(sizeof(GLstencil) == 1);   /*    * 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:         /* 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]) {               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);	       s = (GLstencil) (*sptr & 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]) {               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);	       s = (GLstencil) (*sptr & 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]) {               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);	       s = (GLstencil) (*sptr & 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]) {               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);	       s = (GLstencil) (*sptr & 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]) {               const GLstencil *sptr = STENCIL_ADDRESS(x[i],y[i]);	       s = (GLstencil) (*sptr & valueMask);	       if (r == s) {		  /* passed */		  fail[i] = 0;

⌨️ 快捷键说明

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