Exemplo n.º 1
0
/*
 * 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_TRUE - all fragments failed the testing
 *         GL_FALSE - one or more fragments passed the testing
 */
GLboolean
_mesa_stencil_and_ztest_pixels( GLcontext *ctx,
                                GLuint n, const GLint x[], const GLint y[],
                                const GLdepth z[], GLubyte mask[] )
{
   ASSERT(ctx->Stencil.Enabled);
   ASSERT(n <= PB_SIZE);

   if (ctx->Driver.WriteStencilPixels) {
      /*** Hardware stencil buffer ***/
      GLstencil stencil[PB_SIZE];
      GLubyte origMask[PB_SIZE];

      ASSERT(ctx->Driver.ReadStencilPixels);
      (*ctx->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);

      MEMCPY(origMask, mask, n * sizeof(GLubyte));

      (void) do_stencil_test( ctx, n, stencil, mask );

      if (ctx->Depth.Test == GL_FALSE) {
         apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask );
      }
      else {
         _mesa_depth_test_pixels(ctx, n, x, y, z, mask);

         if (ctx->Stencil.ZFailFunc != GL_KEEP) {
            GLubyte failmask[PB_SIZE];
            GLuint i;
            for (i = 0; i < n; i++) {
               ASSERT(mask[i] == 0 || mask[i] == 1);
               failmask[i] = origMask[i] & (mask[i] ^ 1);
            }
            apply_stencil_op(ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask);
         }
         if (ctx->Stencil.ZPassFunc != GL_KEEP) {
            GLubyte passmask[PB_SIZE];
            GLuint i;
            for (i = 0; i < n; i++) {
               ASSERT(mask[i] == 0 || mask[i] == 1);
               passmask[i] = origMask[i] & mask[i];
            }
            apply_stencil_op(ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask);
         }
      }

      /* Write updated stencil values into hardware stencil buffer */
      (ctx->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, origMask );

      return GL_TRUE;
   }
   else {
      /*** Software stencil buffer ***/

      if (stencil_test_pixels(ctx, 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, mask );
      }
      else {
         GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
         GLuint i;

         MEMCPY(oldmask, mask, n * sizeof(GLubyte));

         _mesa_depth_test_pixels(ctx, n, x, y, z, mask);

         for (i=0;i<n;i++) {
            ASSERT(mask[i] == 0 || mask[i] == 1);
            passmask[i] = oldmask[i] & mask[i];
            failmask[i] = oldmask[i] & (mask[i] ^ 1);
         }

         if (ctx->Stencil.ZFailFunc != GL_KEEP) {
            apply_stencil_op_to_pixels( ctx, n, x, y,
                                        ctx->Stencil.ZFailFunc, failmask );
         }
         if (ctx->Stencil.ZPassFunc != GL_KEEP) {
            apply_stencil_op_to_pixels( ctx, n, x, y,
                                        ctx->Stencil.ZPassFunc, passmask );
         }
      }

      return GL_TRUE;  /* one or more fragments passed both tests */
   }
}
Exemplo n.º 2
0
/*
 * When the pixel buffer is full, or needs to be flushed, call this
 * function.  All the pixels in the pixel buffer will be subjected
 * to texturing, scissoring, stippling, alpha testing, stenciling,
 * depth testing, blending, and finally written to the frame buffer.
 */
void _mesa_flush_pb( GLcontext *ctx )
{
   SWcontext *swrast = SWRAST_CONTEXT(ctx);
   GLuint RasterMask = swrast->_RasterMask;

   /* Pixel colors may be changed if any of these raster ops enabled */
   const GLuint modBits = FOG_BIT | TEXTURE_BIT | BLEND_BIT |
                          MASKING_BIT | LOGIC_OP_BIT;
   struct pixel_buffer *PB = swrast->PB;
   GLubyte mask[PB_SIZE];

   if (PB->count == 0)
      goto CleanUp;

   /* initialize mask array and clip pixels simultaneously */
   {
      const GLint xmin = ctx->DrawBuffer->_Xmin;
      const GLint xmax = ctx->DrawBuffer->_Xmax;
      const GLint ymin = ctx->DrawBuffer->_Ymin;
      const GLint ymax = ctx->DrawBuffer->_Ymax;
      const GLuint n = PB->count;
      GLint *x = PB->x;
      GLint *y = PB->y;
      GLuint i;
      for (i = 0; i < n; i++) {
         mask[i] = (x[i] >= xmin) & (x[i] < xmax) & (y[i] >= ymin) & (y[i] < ymax);
      }
   }

   if (ctx->Visual.rgbMode) {
      /*
       * RGBA COLOR PIXELS
       */

      /* If each pixel can be of a different color... */
      if ((RasterMask & modBits) || !PB->mono) {

         if (PB->mono) {
            /* copy mono color into rgba array */
            GLuint i;
            for (i = 0; i < PB->count; i++) {
               COPY_CHAN4(PB->rgba[i], PB->currentColor);
            }
         }

	 if (ctx->Texture._ReallyEnabled) {
            GLchan primary_rgba[PB_SIZE][4];
            GLuint texUnit;

            /* must make a copy of primary colors since they may be modified */
            MEMCPY(primary_rgba, PB->rgba, 4 * PB->count * sizeof(GLchan));

            for (texUnit = 0; texUnit < ctx->Const.MaxTextureUnits; texUnit++){
               _swrast_texture_fragments( ctx, texUnit, PB->count,
                                          PB->s[texUnit], PB->t[texUnit],
                                          PB->u[texUnit], PB->lambda[texUnit],
                                          (CONST GLchan (*)[4]) primary_rgba,
                                          PB->rgba );
            }
	 }

         if ((ctx->Fog.ColorSumEnabled ||
              (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR
               && ctx->Light.Enabled)) && PB->haveSpec) {
            /* add specular color to primary color */
            add_colors( PB->count, PB->rgba, (const GLchan (*)[3]) PB->spec );
         }

	 if (ctx->Fog.Enabled) {
	    if (swrast->_PreferPixelFog)
	       _mesa_depth_fog_rgba_pixels( ctx, PB->count, PB->z, PB->rgba );
	    else
	       _mesa_fog_rgba_pixels( ctx, PB->count, PB->fog, PB->rgba );
	 }

         /* Antialias coverage application */
         if (PB->haveCoverage) {
            const GLuint n = PB->count;
            GLuint i;
            for (i = 0; i < n; i++) {
               PB->rgba[i][ACOMP] = (GLchan) (PB->rgba[i][ACOMP] * PB->coverage[i]);
            }
         }

         /* Scissoring already done above */

	 if (ctx->Color.AlphaEnabled) {
	    if (_mesa_alpha_test( ctx, PB->count,
                                  (const GLchan (*)[4]) PB->rgba, mask )==0) {
	       goto CleanUp;
	    }
	 }

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (_mesa_stencil_and_ztest_pixels(ctx, PB->count,
                                       PB->x, PB->y, PB->z, mask) == 0) {
	       goto CleanUp;
	    }
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    _mesa_depth_test_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }


         if (RasterMask & MULTI_DRAW_BIT) {
            multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y,
                                     (const GLchan (*)[4])PB->rgba, mask );
         }
         else {
            /* normal case: write to exactly one buffer */
            const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);

            if (ctx->Color.ColorLogicOpEnabled) {
               _mesa_logicop_rgba_pixels( ctx, PB->count, PB->x, PB->y,
                                          PB->rgba, mask);
            }
            else if (ctx->Color.BlendEnabled) {
               _mesa_blend_pixels( ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
            }
            if (colorMask == 0x0) {
               goto CleanUp;
            }
            else if (colorMask != 0xffffffff) {
               _mesa_mask_rgba_pixels(ctx, PB->count, PB->x, PB->y, PB->rgba, mask);
            }

            (*swrast->Driver.WriteRGBAPixels)( ctx, PB->count, PB->x, PB->y,
                                            (const GLchan (*)[4]) PB->rgba,
					    mask );
            if (RasterMask & ALPHABUF_BIT) {
               _mesa_write_alpha_pixels( ctx, PB->count, PB->x, PB->y,
				      (const GLchan (*)[4]) PB->rgba, mask );
            }
         }
      }
      else {
	 /* Same color for all pixels */

         /* Scissoring already done above */

	 if (ctx->Color.AlphaEnabled) {
	    if (_mesa_alpha_test( ctx, PB->count,
                                  (const GLchan (*)[4]) PB->rgba, mask )==0) {
	       goto CleanUp;
	    }
	 }

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (_mesa_stencil_and_ztest_pixels(ctx, PB->count,
                                       PB->x, PB->y, PB->z, mask) == 0) {
	       goto CleanUp;
	    }
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    _mesa_depth_test_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }

         if (ctx->Color.DrawBuffer == GL_NONE) {
            goto CleanUp;
         }

         if (RasterMask & MULTI_DRAW_BIT) {
            if (PB->mono) {
               /* copy mono color into rgba array */
               GLuint i;
               for (i = 0; i < PB->count; i++) {
                  COPY_CHAN4(PB->rgba[i], PB->currentColor);
               }
            }
            multi_write_rgba_pixels( ctx, PB->count, PB->x, PB->y,
                                     (const GLchan (*)[4]) PB->rgba, mask );
         }
         else {
            /* normal case: write to exactly one buffer */
            (*swrast->Driver.WriteMonoRGBAPixels)( ctx, PB->count, PB->x, PB->y,
                                                PB->currentColor, mask );
            if (RasterMask & ALPHABUF_BIT) {
               _mesa_write_mono_alpha_pixels( ctx, PB->count, PB->x, PB->y,
                                              PB->currentColor[ACOMP], mask );
            }
         }
         /*** ALL DONE ***/
      }
   }
   else {
      /*
       * COLOR INDEX PIXELS
       */

      /* If we may be writting pixels with different indexes... */
      if ((RasterMask & modBits) || !PB->mono) {

         if (PB->mono) {
            GLuint i;
            for (i = 0; i < PB->count; i++) {
               PB->index[i] = PB->currentIndex;
            }
         }
	 if (ctx->Fog.Enabled) {
	    if (swrast->_PreferPixelFog)
	       _mesa_depth_fog_ci_pixels( ctx, PB->count, PB->z, PB->index );
	    else
	       _mesa_fog_ci_pixels( ctx, PB->count, PB->fog, PB->index );
	 }

         /* Antialias coverage application */
         if (PB->haveCoverage) {
            const GLuint n = PB->count;
            GLuint i;
            for (i = 0; i < n; i++) {
               GLint frac = (GLint) (15.0 * PB->coverage[i]);
               PB->index[i] = (PB->index[i] & ~0xf) | frac;
            }
         }

         /* Scissoring already done above */

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (_mesa_stencil_and_ztest_pixels(ctx, PB->count,
                                       PB->x, PB->y, PB->z, mask) == 0) {
	       goto CleanUp;
	    }
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    _mesa_depth_test_pixels( ctx, PB->count, PB->x, PB->y, PB->z, mask );
	 }
         if (RasterMask & MULTI_DRAW_BIT) {
            multi_write_index_pixels( ctx, PB->count, PB->x, PB->y, PB->index, mask );
         }
         else {
            /* normal case: write to exactly one buffer */

            if (ctx->Color.IndexLogicOpEnabled) {
               _mesa_logicop_ci_pixels(ctx, PB->count, PB->x, PB->y,
                                       PB->index, mask);
            }
            if (ctx->Color.IndexMask != 0xffffffff) {
               _mesa_mask_index_pixels(ctx, PB->count, PB->x, PB->y,
                                       PB->index, mask);
            }
            (*swrast->Driver.WriteCI32Pixels)( ctx, PB->count, PB->x, PB->y,
                                            PB->index, mask );
         }

         /*** ALL DONE ***/
      }
      else {
	 /* Same color index for all pixels */

         /* Scissoring already done above */

	 if (ctx->Stencil.Enabled) {
	    /* first stencil test */
	    if (_mesa_stencil_and_ztest_pixels(ctx, PB->count,
                                       PB->x, PB->y, PB->z, mask) == 0) {
	       goto CleanUp;
	    }
	 }
	 else if (ctx->Depth.Test) {
	    /* regular depth testing */
	    _mesa_depth_test_pixels(ctx, PB->count, PB->x, PB->y, PB->z, mask);
	 }

         if (RasterMask & MULTI_DRAW_BIT) {
            multi_write_index_pixels(ctx, PB->count, PB->x, PB->y,
                                     PB->index, mask);
         }
         else {
            /* normal case: write to exactly one buffer */
            (*swrast->Driver.WriteMonoCIPixels)(ctx, PB->count, PB->x, PB->y,
                                             PB->currentIndex, mask);
         }
      }
   }

CleanUp:
   PB->count = 0;
   PB->mono = GL_TRUE;
   PB->haveSpec = GL_FALSE;
   PB->haveCoverage = GL_FALSE;
}