From d0130a989a3b331eb8114f1ee4addb95ce31e0e2 Mon Sep 17 00:00:00 2001 From: Brian Paul Date: Tue, 11 Apr 2000 20:42:22 +0000 Subject: [PATCH] clip depth/stencil spans to window bounds --- src/mesa/main/depth.c | 102 ++++++++++++++++++++++++++++++++++++-- src/mesa/main/depth.h | 9 +++- src/mesa/main/drawpix.c | 4 +- src/mesa/main/stencil.c | 107 ++++++++++++++++++++++++---------------- src/mesa/main/stencil.h | 12 ++--- 5 files changed, 178 insertions(+), 56 deletions(-) diff --git a/src/mesa/main/depth.c b/src/mesa/main/depth.c index 88a0a1a69db..8a09206a6a9 100644 --- a/src/mesa/main/depth.c +++ b/src/mesa/main/depth.c @@ -1,4 +1,4 @@ -/* $Id: depth.c,v 1.16 2000/04/04 00:54:23 brianp Exp $ */ +/* $Id: depth.c,v 1.17 2000/04/11 20:42:22 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -1417,6 +1417,74 @@ _mesa_depth_test_pixels( GLcontext *ctx, /**********************************************************************/ +/* + * Read a span of depth values from the depth buffer. + * This function does clipping before calling the device driver function. + */ +void +_mesa_read_depth_span( GLcontext *ctx, + GLint n, GLint x, GLint y, GLdepth depth[] ) +{ + if (y < 0 || y >= ctx->DrawBuffer->Height || + x + (GLint) n <= 0 || x >= ctx->DrawBuffer->Width) { + /* span is completely outside framebuffer */ + GLint i; + for (i = 0; i < n; i++) + depth[i] = 0; + return; + } + + if (x < 0) { + GLint dx = -x; + GLint i; + for (i = 0; i < dx; i++) + depth[i] = 0; + x = 0; + n -= dx; + depth += dx; + } + if (x + n > ctx->DrawBuffer->Width) { + GLint dx = x + n - ctx->DrawBuffer->Width; + GLint i; + for (i = 0; i < dx; i++) + depth[n - i - 1] = 0; + n -= dx; + } + if (n <= 0) { + return; + } + + if (ctx->DrawBuffer->DepthBuffer) { + /* read from software depth buffer */ + if (ctx->Visual->DepthBits <= 16) { + const GLushort *zptr = Z_ADDRESS16( ctx, x, y ); + GLuint i; + for (i = 0; i < n; i++) { + depth[i] = zptr[i]; + } + } + else { + const GLuint *zptr = Z_ADDRESS32( ctx, x, y ); + GLuint i; + for (i = 0; i < n; i++) { + depth[i] = zptr[i]; + } + } + } + else if (ctx->Driver.ReadDepthSpan) { + /* read from hardware depth buffer */ + (*ctx->Driver.ReadDepthSpan)( ctx, n, x, y, depth ); + } + else { + /* no depth buffer */ + BZERO(depth, n * sizeof(GLfloat)); + } + +} + + + + /* * Return a span of depth values from the depth buffer as floats in [0,1]. * This is used for both hardware and software depth buffers. @@ -1425,11 +1493,39 @@ _mesa_depth_test_pixels( GLcontext *ctx, * Output: depth - the array of depth values */ void -_mesa_read_depth_span_float( GLcontext* ctx, - GLuint n, GLint x, GLint y, GLfloat depth[] ) +_mesa_read_depth_span_float( GLcontext *ctx, + GLint n, GLint x, GLint y, GLfloat depth[] ) { const GLfloat scale = 1.0F / ctx->Visual->DepthMaxF; + if (y < 0 || y >= ctx->DrawBuffer->Height || + x + (GLint) n <= 0 || x >= ctx->DrawBuffer->Width) { + /* span is completely outside framebuffer */ + GLint i; + for (i = 0; i < n; i++) + depth[i] = 0.0F; + return; + } + + if (x < 0) { + GLint dx = -x; + GLint i; + for (i = 0; i < dx; i++) + depth[i] = 0.0F; + n -= dx; + x = 0; + } + if (x + n > ctx->DrawBuffer->Width) { + GLint dx = x + n - ctx->DrawBuffer->Width; + GLint i; + for (i = 0; i < dx; i++) + depth[n - i - 1] = 0.0F; + n -= dx; + } + if (n <= 0) { + return; + } + if (ctx->DrawBuffer->DepthBuffer) { /* read from software depth buffer */ if (ctx->Visual->DepthBits <= 16) { diff --git a/src/mesa/main/depth.h b/src/mesa/main/depth.h index ec16ecf37d4..ef176005d4e 100644 --- a/src/mesa/main/depth.h +++ b/src/mesa/main/depth.h @@ -1,4 +1,4 @@ -/* $Id: depth.h,v 1.7 2000/03/03 17:47:39 brianp Exp $ */ +/* $Id: depth.h,v 1.8 2000/04/11 20:42:22 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -68,7 +68,12 @@ _mesa_depth_test_pixels( GLcontext *ctx, extern void -_mesa_read_depth_span_float( GLcontext *ctx, GLuint n, GLint x, GLint y, +_mesa_read_depth_span( GLcontext *ctx, + GLint n, GLint x, GLint y, GLdepth depth[] ); + + +extern void +_mesa_read_depth_span_float( GLcontext *ctx, GLint n, GLint x, GLint y, GLfloat depth[] ); diff --git a/src/mesa/main/drawpix.c b/src/mesa/main/drawpix.c index ad9ce929f10..184248c2706 100644 --- a/src/mesa/main/drawpix.c +++ b/src/mesa/main/drawpix.c @@ -1,4 +1,4 @@ -/* $Id: drawpix.c,v 1.18 2000/04/08 18:57:45 brianp Exp $ */ +/* $Id: drawpix.c,v 1.19 2000/04/11 20:42:22 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -479,7 +479,7 @@ draw_stencil_pixels( GLcontext *ctx, GLint x, GLint y, values, desty ); } else { - gl_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values ); + _mesa_write_stencil_span( ctx, (GLuint) drawWidth, x, y, values ); } } } diff --git a/src/mesa/main/stencil.c b/src/mesa/main/stencil.c index 79c66d3fb2f..ecd610df2e9 100644 --- a/src/mesa/main/stencil.c +++ b/src/mesa/main/stencil.c @@ -1,4 +1,4 @@ -/* $Id: stencil.c,v 1.14 2000/02/02 22:16:04 brianp Exp $ */ +/* $Id: stencil.c,v 1.15 2000/04/11 20:42:22 brianp Exp $ */ /* * Mesa 3-D graphics library @@ -1130,24 +1130,44 @@ gl_stencil_and_depth_test_pixels( GLcontext *ctx, * x,y - location of first pixel * Output: stencil - the array of stencil values */ -void gl_read_stencil_span( GLcontext *ctx, - GLint n, GLint x, GLint y, GLstencil stencil[] ) +void +_mesa_read_stencil_span( GLcontext *ctx, + GLint n, GLint x, GLint y, GLstencil stencil[] ) { + if (y < 0 || y >= ctx->DrawBuffer->Height || + x + n <= 0 || x >= ctx->DrawBuffer->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 > ctx->DrawBuffer->Width) { + GLint dx = x + n - ctx->DrawBuffer->Width; + n -= dx; + } + if (n <= 0) { + return; + } + + ASSERT(n >= 0); - if (ctx->DrawBuffer->Stencil) { - if (ctx->Driver.ReadStencilSpan) { - (*ctx->Driver.ReadStencilSpan)( ctx, (GLuint) n, x, y, stencil ); - } - else { - const GLstencil *s = STENCIL_ADDRESS( x, y ); + if (ctx->Driver.ReadStencilSpan) { + (*ctx->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) ); + MEMCPY( stencil, s, n * sizeof(GLstencil) ); #else - GLuint i; - for (i=0;i= 0); - if (ctx->DrawBuffer->Stencil) { - /* do clipping */ - if (y < ctx->DrawBuffer->Ymin || y > ctx->DrawBuffer->Ymax) - return; - if (x < ctx->DrawBuffer->Xmin) { - GLint diff = ctx->DrawBuffer->Xmin - x; - n -= diff; - stencil += diff; - x = ctx->DrawBuffer->Xmin; - } - if (x + n > ctx->DrawBuffer->Xmax) { - GLint diff = x + n - ctx->DrawBuffer->Xmax; - n -= diff; - } + if (y < 0 || y >= ctx->DrawBuffer->Height || + x + n <= 0 || x >= ctx->DrawBuffer->Width) { + /* span is completely outside framebuffer */ + return; /* undefined values OK */ + } - ASSERT( n >= 0); + if (x < 0) { + GLint dx = -x; + x = 0; + n -= dx; + stencil += dx; + } + if (x + n > ctx->DrawBuffer->Width) { + GLint dx = x + n - ctx->DrawBuffer->Width; + n -= dx; + } + if (n <= 0) { + return; + } - if (ctx->Driver.WriteStencilSpan) { - (*ctx->Driver.WriteStencilSpan)( ctx, n, x, y, stencil, NULL ); - } - else { - GLstencil *s = STENCIL_ADDRESS( x, y ); + if (ctx->Driver.WriteStencilSpan) { + (*ctx->Driver.WriteStencilSpan)( ctx, n, x, y, stencil, NULL ); + } + else if (ctx->DrawBuffer->Stencil) { + GLstencil *s = STENCIL_ADDRESS( x, y ); #if STENCIL_BITS == 8 - MEMCPY( s, stencil, n * sizeof(GLstencil) ); + MEMCPY( s, stencil, n * sizeof(GLstencil) ); #else - GLuint i; - for (i=0;i