X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fmesa%2Fswrast%2Fs_stencil.c;h=43475c0e816e8dabcb8c0fbbb589225ccc1b7bf1;hb=249b451d2068c781d29a6527e152b39d08b1c877;hp=e6282c5af76dd0125e49fb5cc79fa7e30f20497e;hpb=45bc887da226403f2c41077e40ca38b6f60f1359;p=mesa.git diff --git a/src/mesa/swrast/s_stencil.c b/src/mesa/swrast/s_stencil.c index e6282c5af76..43475c0e816 100644 --- a/src/mesa/swrast/s_stencil.c +++ b/src/mesa/swrast/s_stencil.c @@ -1,10 +1,8 @@ -/* $Id: s_stencil.c,v 1.29 2003/03/25 02:23:47 brianp Exp $ */ - /* * Mesa 3-D graphics library - * Version: 4.1 + * Version: 6.5 * - * Copyright (C) 1999-2002 Brian Paul All Rights Reserved. + * 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"), @@ -27,12 +25,12 @@ #include "glheader.h" #include "context.h" -#include "macros.h" #include "imports.h" #include "s_context.h" #include "s_depth.h" #include "s_stencil.h" +#include "s_span.h" @@ -52,14 +50,6 @@ ENDIF */ -/* - * Return the address of a stencil buffer value given the window coords: - */ -#define STENCIL_ADDRESS(X,Y) \ - (ctx->DrawBuffer->Stencil + ctx->DrawBuffer->Width * (Y) + (X)) - - - /** * Apply the given stencil operator to the array of stencil values. * Don't touch stencil[i] if mask[i] is zero. @@ -77,6 +67,7 @@ apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face, 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) { @@ -121,7 +112,7 @@ apply_stencil_op( const GLcontext *ctx, GLenum oper, GLuint face, for (i=0;iDrawBuffer; + struct gl_renderbuffer *rb = fb->_StencilBuffer; GLstencil stencilRow[MAX_WIDTH]; GLstencil *stencil; const GLuint n = span->end; @@ -433,19 +425,13 @@ stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face) ASSERT(span->arrayMask & SPAN_Z); } #endif - - /* Get initial stencil values */ - if (swrast->Driver.WriteStencilSpan) { - /* Get stencil values from the hardware stencil buffer */ - ASSERT(swrast->Driver.ReadStencilSpan); - (*swrast->Driver.ReadStencilSpan)(ctx, n, x, y, stencilRow); + + stencil = (GLstencil *) rb->GetPointer(ctx, rb, x, y); + if (!stencil) { + rb->GetRow(ctx, rb, n, x, y, stencilRow); stencil = stencilRow; } - else { - /* Get pointer into software stencil buffer */ - stencil = STENCIL_ADDRESS(x, y); - } - + /* * Apply the stencil test to the fragments. * failMask[i] is 1 if the stencil test failed. @@ -453,6 +439,10 @@ stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face) 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; } @@ -474,7 +464,7 @@ stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face) GLuint i; /* save the current mask bits */ - MEMCPY(oldmask, mask, n * sizeof(GLubyte)); + _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte)); /* apply the depth test */ _swrast_depth_test_span(ctx, span); @@ -509,9 +499,8 @@ stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face) /* * Write updated stencil values back into hardware stencil buffer. */ - if (swrast->Driver.WriteStencilSpan) { - ASSERT(stencil == stencilRow); - (swrast->Driver.WriteStencilSpan)(ctx, n, x, y, stencil, mask ); + if (!rb->GetPointer(ctx, rb, 0, 0)) { + rb->PutRow(ctx, rb, n, x, y, stencil, NULL); } span->writeAll = GL_FALSE; @@ -521,6 +510,12 @@ stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face) +/* + * 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 @@ -532,16 +527,22 @@ stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span, GLuint face) * mask - array [n] of flag: 1=apply operator, 0=don't apply operator */ static void -apply_stencil_op_to_pixels( const GLcontext *ctx, +apply_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(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); /* software stencil buffer only! */ + ASSERT(rb->GetPointer(ctx, rb, 0, 0)); + ASSERT(sizeof(GLstencil) == 1); switch (oper) { case GL_KEEP: @@ -588,7 +589,7 @@ apply_stencil_op_to_pixels( const GLcontext *ctx, for (i=0;iDrawBuffer; + 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; - /* software stencil buffer only! */ - ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer); - ASSERT(!SWRAST_CONTEXT(ctx)->Driver.ReadStencilSpan); - ASSERT(!SWRAST_CONTEXT(ctx)->Driver.WriteStencilSpan); + ASSERT(rb->GetPointer(ctx, rb, 0, 0)); + ASSERT(sizeof(GLstencil) == 1); /* * Perform stencil test. The results of this operation are stored @@ -742,7 +745,7 @@ stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n, r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;iStencil.Ref[face] & valueMask); for (i=0;iStencil.Ref[face] & valueMask); for (i=0;i s) { /* passed */ @@ -802,7 +805,7 @@ stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n, r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;i= s) { /* passed */ @@ -822,7 +825,7 @@ stencil_test_pixels( GLcontext *ctx, GLuint face, GLuint n, r = (GLstencil) (ctx->Stencil.Ref[face] & valueMask); for (i=0;iStencil.Ref[face] & valueMask); for (i=0;iDrawBuffer; + 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; - SWcontext *swrast = SWRAST_CONTEXT(ctx); ASSERT(span->arrayMask & SPAN_XY); ASSERT(ctx->Stencil.Enabled); ASSERT(n <= MAX_WIDTH); - if (swrast->Driver.WriteStencilPixels) { - /*** Hardware stencil buffer ***/ + if (!rb->GetPointer(ctx, rb, 0, 0)) { + /* No direct access */ GLstencil stencil[MAX_WIDTH]; GLubyte origMask[MAX_WIDTH]; - ASSERT(!ctx->DrawBuffer->UseSoftwareStencilBuffer); - ASSERT(swrast->Driver.ReadStencilPixels); - (*swrast->Driver.ReadStencilPixels)(ctx, n, x, y, stencil); + ASSERT(rb->DataType == GL_UNSIGNED_BYTE); + _swrast_get_values(ctx, rb, n, x, y, stencil, sizeof(GLubyte)); - MEMCPY(origMask, mask, n * sizeof(GLubyte)); + _mesa_memcpy(origMask, mask, n * sizeof(GLubyte)); (void) do_stencil_test(ctx, face, n, stencil, mask); @@ -952,14 +955,12 @@ stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face ) } /* Write updated stencil values into hardware stencil buffer */ - (swrast->Driver.WriteStencilPixels)(ctx, n, x, y, stencil, origMask); + rb->PutValues(ctx, rb, n, x, y, stencil, origMask); return GL_TRUE; } else { - /*** Software stencil buffer ***/ - - ASSERT(ctx->DrawBuffer->UseSoftwareStencilBuffer); + /* 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. */ @@ -974,7 +975,7 @@ stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face ) GLubyte passmask[MAX_WIDTH], failmask[MAX_WIDTH], oldmask[MAX_WIDTH]; GLuint i; - MEMCPY(oldmask, mask, n * sizeof(GLubyte)); + _mesa_memcpy(oldmask, mask, n * sizeof(GLubyte)); _swrast_depth_test_span(ctx, span); @@ -1006,10 +1007,10 @@ stencil_and_ztest_pixels( GLcontext *ctx, struct sw_span *span, GLuint face ) * GL_FALSE = all fragments failed. */ GLboolean -_swrast_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span) +_swrast_stencil_and_ztest_span(GLcontext *ctx, SWspan *span) { /* span->facing can only be non-zero if using two-sided stencil */ - ASSERT(ctx->Stencil.TestTwoSide || span->facing == 0); + ASSERT(ctx->Stencil._TestTwoSide || span->facing == 0); if (span->arrayMask & SPAN_XY) return stencil_and_ztest_pixels(ctx, span, span->facing); else @@ -1017,6 +1018,39 @@ _swrast_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span) } +#if 0 +GLuint +clip_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 @@ -1025,14 +1059,11 @@ _swrast_stencil_and_ztest_span(GLcontext *ctx, struct sw_span *span) * Output: stencil - the array of stencil values */ void -_swrast_read_stencil_span( GLcontext *ctx, - GLint n, GLint x, GLint y, GLstencil stencil[] ) +_swrast_read_stencil_span(GLcontext *ctx, struct gl_renderbuffer *rb, + GLint n, GLint x, GLint y, GLstencil stencil[]) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); - const GLint bufWidth = (GLint) ctx->DrawBuffer->Width; - const GLint bufHeight = (GLint) ctx->DrawBuffer->Height; - - if (y < 0 || y >= bufHeight || x + n <= 0 || x >= bufWidth) { + if (y < 0 || y >= (GLint) rb->Height || + x + n <= 0 || x >= (GLint) rb->Width) { /* span is completely outside framebuffer */ return; /* undefined values OK */ } @@ -1043,285 +1074,189 @@ _swrast_read_stencil_span( GLcontext *ctx, n -= dx; stencil += dx; } - if (x + n > bufWidth) { - GLint dx = x + n - bufWidth; + if (x + n > (GLint) rb->Width) { + GLint dx = x + n - rb->Width; n -= dx; } if (n <= 0) { return; } - - ASSERT(n >= 0); - 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 ); -#if STENCIL_BITS == 8 - MEMCPY( stencil, s, n * sizeof(GLstencil) ); -#else - GLuint i; - for (i=0;iGetRow(ctx, rb, n, x, y, stencil); } /** - * Write a span of stencil values to the stencil buffer. + * 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[] ) +_swrast_write_stencil_span(GLcontext *ctx, GLint n, GLint x, GLint y, + const GLstencil stencil[] ) { - SWcontext *swrast = SWRAST_CONTEXT(ctx); - const GLstencil *ssrc = stencil; - const GLint bufWidth = (GLint) ctx->DrawBuffer->Width; - const GLint bufHeight = (GLint) ctx->DrawBuffer->Height; + 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 >= bufHeight || x + n <= 0 || x >= bufWidth) { + 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; - ssrc += dx; + stencil += dx; } - if (x + n > bufWidth) { - GLint dx = x + n - bufWidth; + if (x + n > (GLint) rb->Width) { + GLint dx = x + n - rb->Width; n -= dx; } if (n <= 0) { return; } - if (swrast->Driver.WriteStencilSpan) { - (*swrast->Driver.WriteStencilSpan)( ctx, n, x, y, ssrc, NULL ); + 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 if (ctx->DrawBuffer->Stencil) { - GLstencil *s = STENCIL_ADDRESS( x, y ); -#if STENCIL_BITS == 8 - MEMCPY( s, ssrc, n * sizeof(GLstencil) ); -#else - GLuint i; - for (i=0;iPutRow(ctx, rb, n, x, y, stencil, NULL); } } /** - * Allocate a new stencil buffer. If there's an old one it will be - * deallocated first. The new stencil buffer will be uninitialized. + * Clear the stencil buffer. */ void -_swrast_alloc_stencil_buffer( GLframebuffer *buffer ) -{ - /* deallocate current stencil buffer if present */ - if (buffer->Stencil) { - MESA_PBUFFER_FREE(buffer->Stencil); - buffer->Stencil = NULL; - } - - /* allocate new stencil buffer */ - buffer->Stencil = (GLstencil *) - MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height * sizeof(GLstencil)); - if (!buffer->Stencil) { - /* out of memory */ - _mesa_error( NULL, GL_OUT_OF_MEMORY, "_swrast_alloc_stencil_buffer" ); - } -} - - - -/** - * Clear the software (malloc'd) stencil buffer. - */ -static void -clear_software_stencil_buffer( GLcontext *ctx ) +_swrast_clear_stencil_buffer( GLcontext *ctx, struct gl_renderbuffer *rb ) { - if (ctx->Visual.stencilBits==0 || !ctx->DrawBuffer->Stencil) { - /* no stencil buffer */ + 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 || !rb->Data) return; - } - if (ctx->Scissor.Enabled) { - /* clear scissor region only */ - const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { - /* must apply mask to the clear */ - GLint y; - for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) { - const GLstencil mask = ctx->Stencil.WriteMask[0]; - const GLstencil invMask = ~mask; - const GLstencil clearVal = (ctx->Stencil.Clear & mask); - GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y ); - GLint i; - for (i = 0; i < width; i++) { - stencil[i] = (stencil[i] & invMask) | clearVal; + 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 { - /* no masking */ - GLint y; - for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) { - GLstencil *stencil = STENCIL_ADDRESS( ctx->DrawBuffer->_Xmin, y ); -#if STENCIL_BITS==8 - MEMSET( stencil, ctx->Stencil.Clear, width * sizeof(GLstencil) ); -#else - GLint i; - for (i = 0; i < width; i++) - stencil[x] = ctx->Stencil.Clear; -#endif - } - } - } - else { - /* clear whole stencil buffer */ - if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { - /* must apply mask to the clear */ - const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; - GLstencil *stencil = ctx->DrawBuffer->Stencil; - const GLstencil mask = ctx->Stencil.WriteMask[0]; - const GLstencil invMask = ~mask; - const GLstencil clearVal = (ctx->Stencil.Clear & mask); - GLuint i; - for (i = 0; i < n; i++) { - stencil[i] = (stencil[i] & 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 { - /* clear whole buffer without masking */ - const GLuint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; - GLstencil *stencil = ctx->DrawBuffer->Stencil; - -#if STENCIL_BITS==8 - MEMSET(stencil, ctx->Stencil.Clear, n * sizeof(GLstencil) ); -#else - GLuint i; - for (i = 0; i < n; i++) { - stencil[i] = ctx->Stencil.Clear; + /* 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); } -#endif - } - } -} - - - -/** - * Clear the hardware (in graphics card) stencil buffer. - * This is done with the Driver.WriteStencilSpan() and Driver.ReadStencilSpan() - * functions. - * Actually, if there is a hardware stencil buffer it really should have - * been cleared in Driver.Clear()! However, if the hardware does not - * support scissored clears or masked clears (i.e. glStencilMask) then - * we have to use the span-based functions. - */ -static void -clear_hardware_stencil_buffer( GLcontext *ctx ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - ASSERT(swrast->Driver.WriteStencilSpan); - ASSERT(swrast->Driver.ReadStencilSpan); - - if (ctx->Scissor.Enabled) { - /* clear scissor region only */ - const GLint x = ctx->DrawBuffer->_Xmin; - const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; - if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { - /* must apply mask to the clear */ - GLint y; - for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) { - const GLstencil mask = ctx->Stencil.WriteMask[0]; - const GLstencil invMask = ~mask; - const GLstencil clearVal = (ctx->Stencil.Clear & mask); - GLstencil stencil[MAX_WIDTH]; + else { + /* general case */ GLint i; - (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil); - for (i = 0; i < width; i++) { - stencil[i] = (stencil[i] & invMask) | clearVal; + 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); + } } - (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL); - } - } - else { - /* no masking */ - GLstencil stencil[MAX_WIDTH]; - GLint y, i; - for (i = 0; i < width; i++) { - stencil[i] = ctx->Stencil.Clear; - } - for (y = ctx->DrawBuffer->_Ymin; y < ctx->DrawBuffer->_Ymax; y++) { - (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL); } } } else { - /* clear whole stencil buffer */ - if (ctx->Stencil.WriteMask[0] != STENCIL_MAX) { - /* must apply mask to the clear */ - const GLstencil mask = ctx->Stencil.WriteMask[0]; - const GLstencil invMask = ~mask; - const GLstencil clearVal = (ctx->Stencil.Clear & mask); - const GLint width = ctx->DrawBuffer->Width; - const GLint height = ctx->DrawBuffer->Height; - const GLint x = ctx->DrawBuffer->_Xmin; - GLint y; - for (y = 0; y < height; y++) { - GLstencil stencil[MAX_WIDTH]; - GLint i; - (*swrast->Driver.ReadStencilSpan)(ctx, width, x, y, stencil); - for (i = 0; i < width; i++) { - stencil[i] = (stencil[i] & invMask) | clearVal; + /* 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); } - (*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->Height; - const GLint x = ctx->DrawBuffer->_Xmin; - GLstencil stencil[MAX_WIDTH]; - GLint y, i; - for (i = 0; i < width; i++) { - stencil[i] = ctx->Stencil.Clear; + /* 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; } - for (y = 0; y < height; y++) { - (*swrast->Driver.WriteStencilSpan)(ctx, width, x, y, stencil, NULL); + else { + clear = &clear16; + } + for (i = 0; i < height; i++) { + rb->PutMonoRow(ctx, rb, width, x, y + i, clear, NULL); } } } } - - - -/** - * Clear the stencil buffer (hardware or software). - */ -void -_swrast_clear_stencil_buffer( GLcontext *ctx ) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - if (swrast->Driver.WriteStencilSpan) { - ASSERT(swrast->Driver.ReadStencilSpan); - clear_hardware_stencil_buffer(ctx); - } - else { - clear_software_stencil_buffer(ctx); - } -}