-/* $Id: s_stencil.c,v 1.5 2001/01/23 23:39:37 brianp Exp $ */
+/* $Id: s_stencil.c,v 1.12 2001/05/17 20:18:45 brianp Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.5
- *
- * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
- *
+ *
+ * Copyright (C) 1999-2001 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
/* Stencil Logic:
IF stencil test fails THEN
- Apply fail-op to stencil value
+ 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
+ Apply zfail-op to stencil value
Write RGBA and Z to appropriate buffers
ELSE
Apply zpass-op to stencil value
}
break;
default:
- gl_problem(ctx, "Bad stencil op in apply_stencil_op");
+ _mesa_problem(ctx, "Bad stencil op in apply_stencil_op");
}
}
}
break;
default:
- gl_problem(ctx, "Bad stencil func in gl_stencil_span");
+ _mesa_problem(ctx, "Bad stencil func in gl_stencil_span");
return 0;
}
* 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
- *
+ *
*/
static GLboolean
stencil_and_ztest_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
* 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_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
const GLdepth z[], GLubyte mask[] )
{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
GLstencil stencilRow[MAX_WIDTH];
GLstencil *stencil;
GLboolean result;
ASSERT(n <= MAX_WIDTH);
/* Get initial stencil values */
- if (ctx->Driver.WriteStencilSpan) {
- ASSERT(ctx->Driver.ReadStencilSpan);
+ if (swrast->Driver.WriteStencilSpan) {
+ ASSERT(swrast->Driver.ReadStencilSpan);
/* Get stencil values from the hardware stencil buffer */
- (*ctx->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
+ (*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow);
stencil = stencilRow;
}
else {
/* do all the stencil/depth testing/updating */
result = stencil_and_ztest_span( ctx, n, x, y, z, stencil, mask );
- if (ctx->Driver.WriteStencilSpan) {
+ if (swrast->Driver.WriteStencilSpan) {
/* Write updated stencil values into hardware stencil buffer */
- (ctx->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
+ (swrast->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask );
}
return result;
const GLstencil invmask = (GLstencil) (~ctx->Stencil.WriteMask);
GLuint i;
- ASSERT(!ctx->Driver.WriteStencilSpan); /* software stencil buffer only! */
+ ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* software stencil buffer only! */
switch (oper) {
case GL_KEEP:
}
break;
default:
- gl_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
+ _mesa_problem(ctx, "Bad stencilop in apply_stencil_op_to_pixels");
}
}
GLuint i;
GLboolean allfail = GL_FALSE;
- ASSERT(!ctx->Driver.WriteStencilSpan); /* software stencil buffer only! */
+ ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* software stencil buffer only! */
/*
* Perform stencil test. The results of this operation are stored
}
break;
default:
- gl_problem(ctx, "Bad stencil func in gl_stencil_pixels");
+ _mesa_problem(ctx, "Bad stencil func in gl_stencil_pixels");
return 0;
}
* 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
GLuint n, const GLint x[], const GLint y[],
const GLdepth z[], GLubyte mask[] )
{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
ASSERT(ctx->Stencil.Enabled);
ASSERT(n <= PB_SIZE);
- if (ctx->Driver.WriteStencilPixels) {
+ if (swrast->Driver.WriteStencilPixels) {
/*** Hardware stencil buffer ***/
GLstencil stencil[PB_SIZE];
- GLubyte mask[PB_SIZE];
+ GLubyte origMask[PB_SIZE];
- ASSERT(ctx->Driver.ReadStencilPixels);
- (*ctx->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);
+ ASSERT(swrast->Driver.ReadStencilPixels);
+ (*swrast->Driver.ReadStencilPixels)(ctx, n, x, y, stencil);
+ MEMCPY(origMask, mask, n * sizeof(GLubyte));
- if (do_stencil_test( ctx, n, stencil, mask ) == GL_FALSE) {
- /* all fragments failed the stencil test, we're done. */
- return GL_FALSE;
- }
+ (void) do_stencil_test(ctx, n, stencil, mask);
if (ctx->Depth.Test == GL_FALSE) {
- apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, mask );
+ apply_stencil_op(ctx, ctx->Stencil.ZPassFunc, n, stencil, 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( ctx, ctx->Stencil.ZFailFunc, n, stencil, failmask );
+ 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) {
- apply_stencil_op( ctx, ctx->Stencil.ZPassFunc, n, stencil, passmask );
+ 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, mask );
+ (swrast->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, origMask);
return GL_TRUE;
-
}
else {
/*** Software stencil buffer ***/
return GL_FALSE;
}
-
if (ctx->Depth.Test==GL_FALSE) {
- apply_stencil_op_to_pixels( ctx, n, x, y, ctx->Stencil.ZPassFunc, mask );
+ apply_stencil_op_to_pixels(ctx, n, x, y,
+ ctx->Stencil.ZPassFunc, mask);
}
else {
GLubyte passmask[PB_SIZE], failmask[PB_SIZE], oldmask[PB_SIZE];
}
if (ctx->Stencil.ZFailFunc != GL_KEEP) {
- apply_stencil_op_to_pixels( ctx, n, x, y,
- ctx->Stencil.ZFailFunc, failmask );
+ 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 );
+ apply_stencil_op_to_pixels(ctx, n, x, y,
+ ctx->Stencil.ZPassFunc, passmask);
}
}
_mesa_read_stencil_span( GLcontext *ctx,
GLint n, GLint x, GLint y, GLstencil stencil[] )
{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (y < 0 || y >= ctx->DrawBuffer->Height ||
x + n <= 0 || x >= ctx->DrawBuffer->Width) {
/* span is completely outside framebuffer */
ASSERT(n >= 0);
- if (ctx->Driver.ReadStencilSpan) {
- (*ctx->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil );
+ if (swrast->Driver.ReadStencilSpan) {
+ (*swrast->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil );
}
else if (ctx->DrawBuffer->Stencil) {
const GLstencil *s = STENCIL_ADDRESS( x, y );
_mesa_write_stencil_span( GLcontext *ctx, GLint n, GLint x, GLint y,
const GLstencil stencil[] )
{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
if (y < 0 || y >= ctx->DrawBuffer->Height ||
x + n <= 0 || x >= ctx->DrawBuffer->Width) {
/* span is completely outside framebuffer */
return;
}
- if (ctx->Driver.WriteStencilSpan) {
- (*ctx->Driver.WriteStencilSpan)( ctx, n, x, y, stencil, NULL );
+ if (swrast->Driver.WriteStencilSpan) {
+ (*swrast->Driver.WriteStencilSpan)( ctx, n, x, y, stencil, NULL );
}
else if (ctx->DrawBuffer->Stencil) {
GLstencil *s = STENCIL_ADDRESS( x, y );
if (!ctx->DrawBuffer->Stencil) {
/* out of memory */
/* _mesa_set_enable( ctx, GL_STENCIL_TEST, GL_FALSE ); */
- gl_error( ctx, GL_OUT_OF_MEMORY, "_mesa_alloc_stencil_buffer" );
+ _mesa_error( ctx, GL_OUT_OF_MEMORY, "_mesa_alloc_stencil_buffer" );
}
}
static void
clear_hardware_stencil_buffer( GLcontext *ctx )
{
- ASSERT(ctx->Driver.WriteStencilSpan);
- ASSERT(ctx->Driver.ReadStencilSpan);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ ASSERT(swrast->Driver.WriteStencilSpan);
+ ASSERT(swrast->Driver.ReadStencilSpan);
if (ctx->Scissor.Enabled) {
/* clear scissor region only */
const GLstencil clearVal = (ctx->Stencil.Clear & mask);
GLstencil stencil[MAX_WIDTH];
GLint i;
- (*ctx->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
+ (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
for (i = 0; i < width; i++) {
stencil[i] = (stencil[i] & invMask) | clearVal;
}
- (*ctx->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
+ (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
else {
stencil[i] = ctx->Stencil.Clear;
}
for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) {
- (*ctx->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
+ (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
}
GLint y;
for (y = 0; y < height; y++) {
GLstencil stencil[MAX_WIDTH];
- GLuint i;
- (*ctx->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
+ GLint i;
+ (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil);
for (i = 0; i < width; i++) {
stencil[i] = (stencil[i] & invMask) | clearVal;
}
- (*ctx->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
+ (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
else {
/* clear whole buffer without masking */
const GLint width = ctx->DrawBuffer->Width;
- const GLint height = ctx->DrawBuffer->Width;
+ const GLint height = ctx->DrawBuffer->Height;
const GLint x = ctx->DrawBuffer->_Xmin;
GLstencil stencil[MAX_WIDTH];
GLint y, i;
stencil[i] = ctx->Stencil.Clear;
}
for (y = 0; y < height; y++) {
- (*ctx->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
+ (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL);
}
}
}
void
_mesa_clear_stencil_buffer( GLcontext *ctx )
{
- if (ctx->Driver.WriteStencilSpan) {
- ASSERT(ctx->Driver.ReadStencilSpan);
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ if (swrast->Driver.WriteStencilSpan) {
+ ASSERT(swrast->Driver.ReadStencilSpan);
clear_hardware_stencil_buffer(ctx);
}
else {
clear_software_stencil_buffer(ctx);
}
}
-