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

📄 s_stencil.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 3 页
字号:
	       }	       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]) {               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_ALWAYS:	 /* always pass */	 for (i=0;i<n;i++) {	    fail[i] = 0;	 }	 break;      default:         _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");         return 0;   }   if (ctx->Stencil.FailFunc[face] != GL_KEEP) {      apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.FailFunc[face],                                  face, fail );   }   return !allfail;}/** * Apply stencil and depth testing to an array of pixels. * This is used both for software and hardware stencil buffers. * * The comments in this function are a bit sparse but the code is * almost identical to stencil_and_ztest_span(), which is well * commented. * * Input:  n - number of pixels in the array *         x, y - array of [n] pixel positions *         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_pixels( GLcontext *ctx, SWspan *span, GLuint face ){   GLubyte passMask[MAX_WIDTH], failMask[MAX_WIDTH], origMask[MAX_WIDTH];   struct gl_framebuffer *fb = ctx->DrawBuffer;   struct gl_renderbuffer *rb = fb->_StencilBuffer;   const GLuint n = span->end;   const GLint *x = span->array->x;   const GLint *y = span->array->y;   GLubyte *mask = span->array->mask;   ASSERT(span->arrayMask & SPAN_XY);   ASSERT(ctx->Stencil.Enabled);   ASSERT(n <= MAX_WIDTH);   if (!rb->GetPointer(ctx, rb, 0, 0)) {      /* No direct access */      GLstencil stencil[MAX_WIDTH];      ASSERT(rb->DataType == GL_UNSIGNED_BYTE);      _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte));      _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));                (void) do_stencil_test(ctx, face, n, stencil, mask);      if (ctx->Depth.Test == GL_FALSE) {         apply_stencil_op(ctx, ctx->Stencil.ZPassFunc[face], face,                          n, stencil, mask);      }      else {         GLubyte tmpMask[MAX_WIDTH];          _mesa_memcpy(tmpMask, mask, n * sizeof(GLubyte));         _swrast_depth_test_span(ctx, span);         compute_pass_fail_masks(n, tmpMask, mask, passMask, failMask);         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 into hardware stencil buffer */      rb->PutValues(ctx, rb, n, x, y, stencil, origMask);      return GL_TRUE;   }   else {      /* Direct access to stencil buffer */      if (stencil_test_pixels(ctx, face, n, x, y, mask) == GL_FALSE) {         /* all fragments failed the stencil test, we're done. */         return GL_FALSE;      }      if (ctx->Depth.Test==GL_FALSE) {         apply_stencil_op_to_pixels(ctx, n, x, y,                                    ctx->Stencil.ZPassFunc[face], face, mask);      }      else {         _mesa_memcpy(origMask, mask, n * sizeof(GLubyte));         _swrast_depth_test_span(ctx, span);         compute_pass_fail_masks(n, origMask, mask, passMask, failMask);         if (ctx->Stencil.ZFailFunc[face] != GL_KEEP) {            apply_stencil_op_to_pixels(ctx, n, x, y,                                       ctx->Stencil.ZFailFunc[face],                                       face, failMask);         }         if (ctx->Stencil.ZPassFunc[face] != GL_KEEP) {            apply_stencil_op_to_pixels(ctx, n, x, y,                                       ctx->Stencil.ZPassFunc[face],                                       face, passMask);         }      }      return GL_TRUE;  /* one or more fragments passed both tests */   }}/** * /return GL_TRUE = one or more fragments passed, * GL_FALSE = all fragments failed. */GLboolean_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span){   if (span->arrayMask & SPAN_XY)      return stencil_and_ztest_pixels(ctx, span, span->facing);   else      return stencil_and_ztest_span(ctx, span, span->facing);}#if 0GLuintclip_span(GLuint bufferWidth, GLuint bufferHeight,          GLint x, GLint y, GLuint *count){   GLuint n = *count;   GLuint skipPixels = 0;   if (y < 0 || y >= bufferHeight || x + n <= 0 || x >= bufferWidth) {      /* totally out of bounds */      n = 0;   }   else {      /* left clip */      if (x < 0) {         skipPixels = -x;         x = 0;         n -= skipPixels;      }      /* right clip */      if (x + n > bufferWidth) {         GLint dx = x + n - bufferWidth;         n -= dx;      }   }   *count = n;   return skipPixels;}#endif/** * Return a span of stencil values from the stencil buffer. * Used for glRead/CopyPixels * Input:  n - how many pixels *         x,y - location of first pixel * Output:  stencil - the array of stencil values */void_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb,                          GLint n, GLint x, GLint y, GLstencil stencil[]){   if (y < 0 || y >= (GLint) rb->Height ||       x + n <= 0 || x >= (GLint) rb->Width) {      /* span is completely outside framebuffer */      return; /* undefined values OK */   }   if (x < 0) {      GLint dx = -x;      x = 0;      n -= dx;      stencil += dx;   }   if (x + n > (GLint) rb->Width) {      GLint dx = x + n - rb->Width;      n -= dx;   }   if (n <= 0) {      return;   }   rb->GetRow(ctx, rb, n, x, y, stencil);}/** * Write a span of stencil values to the stencil buffer.  This function * applies the stencil write mask when needed. * Used for glDraw/CopyPixels * Input:  n - how many pixels *         x, y - location of first pixel *         stencil - the array of stencil values */void_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y,                           const GLstencil stencil[] ){   struct gl_framebuffer *fb = ctx->DrawBuffer;   struct gl_renderbuffer *rb = fb->_StencilBuffer;   const GLuint stencilMax = (1 << fb->Visual.stencilBits) - 1;   const GLuint stencilMask = ctx->Stencil.WriteMask[0];   if (y < 0 || y >= (GLint) rb->Height ||       x + n <= 0 || x >= (GLint) rb->Width) {      /* span is completely outside framebuffer */      return; /* undefined values OK */   }   if (x < 0) {      GLint dx = -x;      x = 0;      n -= dx;      stencil += dx;   }   if (x + n > (GLint) rb->Width) {      GLint dx = x + n - rb->Width;      n -= dx;   }   if (n <= 0) {      return;   }   if ((stencilMask & stencilMax) != stencilMax) {      /* need to apply writemask */      GLstencil destVals[MAX_WIDTH], newVals[MAX_WIDTH];      GLint i;      rb->GetRow(ctx, rb, n, x, y, destVals);      for (i = 0; i < n; i++) {         newVals[i]            = (stencil[i] & stencilMask) | (destVals[i] & ~stencilMask);      }      rb->PutRow(ctx, rb, n, x, y, newVals, NULL);   }   else {      rb->PutRow(ctx, rb, n, x, y, stencil, NULL);   }}/** * Clear the stencil buffer. */void_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb ){   const GLubyte stencilBits = ctx->DrawBuffer->Visual.stencilBits;   const GLuint mask = ctx->Stencil.WriteMask[0];   const GLuint invMask = ~mask;   const GLuint clearVal = (ctx->Stencil.Clear & mask);   const GLuint stencilMax = (1 << stencilBits) - 1;   GLint x, y, width, height;   if (!rb || mask == 0)      return;   ASSERT(rb->DataType == GL_UNSIGNED_BYTE ||          rb->DataType == GL_UNSIGNED_SHORT);   ASSERT(rb->_BaseFormat == GL_STENCIL_INDEX);   /* compute region to clear */   x = ctx->DrawBuffer->_Xmin;   y = ctx->DrawBuffer->_Ymin;   width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;   height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;   if (rb->GetPointer(ctx, rb, 0, 0)) {      /* Direct buffer access */      if ((mask & stencilMax) != stencilMax) {         /* need to mask the clear */         if (rb->DataType == GL_UNSIGNED_BYTE) {            GLint i, j;            for (i = 0; i < height; i++) {               GLubyte *stencil = (GLubyte*) rb->GetPointer(ctx, rb, x, y + i);               for (j = 0; j < width; j++) {                  stencil[j] = (stencil[j] & invMask) | clearVal;               }            }         }         else {            GLint i, j;            for (i = 0; i < height; i++) {               GLushort *stencil = (GLushort*) rb->GetPointer(ctx, rb, x, y + i);               for (j = 0; j < width; j++) {                  stencil[j] = (stencil[j] & invMask) | clearVal;               }            }         }      }      else {         /* no bit masking */         if (width == (GLint) rb->Width && rb->DataType == GL_UNSIGNED_BYTE) {            /* optimized case */            /* Note: bottom-to-top raster assumed! */            GLubyte *stencil = (GLubyte *) rb->GetPointer(ctx, rb, x, y);            GLuint len = width * height * sizeof(GLubyte);            _mesa_memset(stencil, clearVal, len);         }         else {            /* general case */            GLint i;            for (i = 0; i < height; i++) {               GLvoid *stencil = rb->GetPointer(ctx, rb, x, y + i);               if (rb->DataType == GL_UNSIGNED_BYTE) {                  _mesa_memset(stencil, clearVal, width);               }               else {                  _mesa_memset16((short unsigned int*) stencil, clearVal, width);               }            }         }      }   }   else {      /* no direct access */      if ((mask & stencilMax) != stencilMax) {         /* need to mask the clear */         if (rb->DataType == GL_UNSIGNED_BYTE) {            GLint i, j;            for (i = 0; i < height; i++) {               GLubyte stencil[MAX_WIDTH];               rb->GetRow(ctx, rb, width, x, y + i, stencil);               for (j = 0; j < width; j++) {                  stencil[j] = (stencil[j] & invMask) | clearVal;               }               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);            }         }         else {            GLint i, j;            for (i = 0; i < height; i++) {               GLushort stencil[MAX_WIDTH];               rb->GetRow(ctx, rb, width, x, y + i, stencil);               for (j = 0; j < width; j++) {                  stencil[j] = (stencil[j] & invMask) | clearVal;               }               rb->PutRow(ctx, rb, width, x, y + i, stencil, NULL);            }         }      }      else {         /* no bit masking */         const GLubyte clear8 = (GLubyte) clearVal;         const GLushort clear16 = (GLushort) clearVal;         const void *clear;         GLint i;         if (rb->DataType == GL_UNSIGNED_BYTE) {            clear = &clear8;         }         else {            clear = &clear16;         }         for (i = 0; i < height; i++) {            rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL);         }      }   }}

⌨️ 快捷键说明

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