diff options
| author | Radosław Kujawa <radoslaw.kujawa@c0ff33.net> | 2026-07-17 14:54:32 +0200 |
|---|---|---|
| committer | Radosław Kujawa <radoslaw.kujawa@c0ff33.net> | 2026-07-17 14:54:32 +0200 |
| commit | 2702c90d7a39fca2a3319c5e915fd290cb31fc70 (patch) | |
| tree | 283c4d851efef7e3a7cd03ba80c87e2bffcdbb2c /src/mesa/swrast/s_depth.c | |
| parent | 836167945ec2c7ad5acdf0aa17ce35ec1b9428a6 (diff) | |
Initial import.
Diffstat (limited to 'src/mesa/swrast/s_depth.c')
| -rw-r--r-- | src/mesa/swrast/s_depth.c | 1797 |
1 files changed, 1797 insertions, 0 deletions
diff --git a/src/mesa/swrast/s_depth.c b/src/mesa/swrast/s_depth.c new file mode 100644 index 0000000..34897ba --- /dev/null +++ b/src/mesa/swrast/s_depth.c @@ -0,0 +1,1797 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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 + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#include "glheader.h" +#include "context.h" +#include "macros.h" +#include "imports.h" + +#include "s_depth.h" +#include "s_context.h" + + +/** + * Return address of depth buffer value for given window coord. + */ +GLvoid * +_swrast_zbuffer_address(GLcontext *ctx, GLint x, GLint y) +{ + if (ctx->Visual.depthBits <= 16) + return (GLushort *) ctx->DrawBuffer->DepthBuffer + + ctx->DrawBuffer->Width * y + x; + else + return (GLuint *) ctx->DrawBuffer->DepthBuffer + + ctx->DrawBuffer->Width * y + x; +} + + +#define Z_ADDRESS16( CTX, X, Y ) \ + ( ((GLushort *) (CTX)->DrawBuffer->DepthBuffer) \ + + (CTX)->DrawBuffer->Width * (Y) + (X) ) + +#define Z_ADDRESS32( CTX, X, Y ) \ + ( ((GLuint *) (CTX)->DrawBuffer->DepthBuffer) \ + + (CTX)->DrawBuffer->Width * (Y) + (X) ) + + + +/**********************************************************************/ +/***** Depth Testing Functions *****/ +/**********************************************************************/ + + +/* + * Do depth test for an array of fragments. This is used both for + * software and hardware Z buffers. + * Input: zbuffer - array of z values in the zbuffer + * z - array of fragment z values + * Return: number of fragments which pass the test. + */ +static GLuint +depth_test_span16( GLcontext *ctx, GLuint n, + GLushort zbuffer[], const GLdepth z[], GLubyte mask[] ) +{ + GLuint passed = 0; + + /* switch cases ordered from most frequent to less frequent */ + switch (ctx->Depth.Func) { + case GL_LESS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] < zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + passed++; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] < zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_LEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] <= zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] <= zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_GEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] >= zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] >= zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] > zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] > zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] != zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] != zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_EQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] == zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] == zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_ALWAYS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + zbuffer[i] = z[i]; + passed++; + } + } + } + else { + /* Don't update Z buffer or mask */ + passed = n; + } + break; + case GL_NEVER: + _mesa_bzero(mask, n * sizeof(GLubyte)); + break; + default: + _mesa_problem(ctx, "Bad depth func in depth_test_span16"); + } + + return passed; +} + + +static GLuint +depth_test_span32( GLcontext *ctx, GLuint n, + GLuint zbuffer[], const GLdepth z[], GLubyte mask[] ) +{ + GLuint passed = 0; + + /* switch cases ordered from most frequent to less frequent */ + switch (ctx->Depth.Func) { + case GL_LESS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] < zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + passed++; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] < zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_LEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] <= zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] <= zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_GEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] >= zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] >= zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] > zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] > zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] != zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] != zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_EQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] == zbuffer[i]) { + zbuffer[i] = z[i]; + passed++; + } + else { + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + if (z[i] == zbuffer[i]) { + /* pass */ + passed++; + } + else { + mask[i] = 0; + } + } + } + } + break; + case GL_ALWAYS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0;i<n;i++) { + if (mask[i]) { + zbuffer[i] = z[i]; + passed++; + } + } + } + else { + /* Don't update Z buffer or mask */ + passed = n; + } + break; + case GL_NEVER: + _mesa_bzero(mask, n * sizeof(GLubyte)); + break; + default: + _mesa_problem(ctx, "Bad depth func in depth_test_span32"); + } + + return passed; +} + + + +/* + * Apply depth test to span of fragments. Hardware or software z buffer. + */ +static GLuint +depth_test_span( GLcontext *ctx, struct sw_span *span) +{ + const GLint x = span->x; + const GLint y = span->y; + const GLuint n = span->end; + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + ASSERT((span->arrayMask & SPAN_XY) == 0); + ASSERT(span->arrayMask & SPAN_Z); + + if (swrast->Driver.ReadDepthSpan) { + /* hardware-based depth buffer */ + GLdepth zbuffer[MAX_WIDTH]; + GLuint passed; + (*swrast->Driver.ReadDepthSpan)(ctx, n, x, y, zbuffer); + passed = depth_test_span32(ctx, n, zbuffer, span->array->z, + span->array->mask); + ASSERT(swrast->Driver.WriteDepthSpan); + (*swrast->Driver.WriteDepthSpan)(ctx, n, x, y, zbuffer, + span->array->mask); + if (passed < n) + span->writeAll = GL_FALSE; + return passed; + } + else { + GLuint passed; + /* software depth buffer */ + if (ctx->Visual.depthBits <= 16) { + GLushort *zptr = (GLushort *) Z_ADDRESS16(ctx, x, y); + passed = depth_test_span16(ctx, n, zptr, span->array->z, span->array->mask); + } + else { + GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, x, y); + passed = depth_test_span32(ctx, n, zptr, span->array->z, span->array->mask); + } +#if 1 + if (passed < span->end) { + span->writeAll = GL_FALSE; + } +#else + /* this causes a glDrawPixels(GL_DEPTH_COMPONENT) conformance failure */ + if (passed < span->end) { + span->writeAll = GL_FALSE; + if (passed == 0) { + span->end = 0; + return 0; + } + while (span->end > 0 && span->mask[span->end - 1] == 0) + span->end --; + } +#endif + return passed; + } +} + + + + +/* + * Do depth testing for an array of fragments using software Z buffer. + */ +static void +software_depth_test_pixels16( GLcontext *ctx, GLuint n, + const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ) +{ + /* switch cases ordered from most frequent to less frequent */ + switch (ctx->Depth.Func) { + case GL_LESS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] < *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] < *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_LEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] <= *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] <= *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] >= *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] >= *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] > *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] > *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] != *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] != *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_EQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] == *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + if (z[i] == *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_ALWAYS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]); + *zptr = z[i]; + } + } + } + else { + /* Don't update Z buffer or mask */ + } + break; + case GL_NEVER: + /* depth test never passes */ + _mesa_bzero(mask, n * sizeof(GLubyte)); + break; + default: + _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels"); + } +} + + + +/* + * Do depth testing for an array of fragments using software Z buffer. + */ +static void +software_depth_test_pixels32( GLcontext *ctx, GLuint n, + const GLint x[], const GLint y[], + const GLdepth z[], GLubyte mask[] ) +{ + /* switch cases ordered from most frequent to less frequent */ + switch (ctx->Depth.Func) { + case GL_LESS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] < *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] < *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_LEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] <= *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] <= *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] >= *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] >= *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] > *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] > *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] != *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] != *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_EQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] == *zptr) { + /* pass */ + *zptr = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + if (z[i] == *zptr) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_ALWAYS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]); + *zptr = z[i]; + } + } + } + else { + /* Don't update Z buffer or mask */ + } + break; + case GL_NEVER: + /* depth test never passes */ + _mesa_bzero(mask, n * sizeof(GLubyte)); + break; + default: + _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels"); + } +} + + + +/* + * Do depth testing for an array of pixels using hardware Z buffer. + * Input/output: zbuffer - array of depth values from Z buffer + * Input: z - array of fragment z values. + */ +static void +hardware_depth_test_pixels( GLcontext *ctx, GLuint n, GLdepth zbuffer[], + const GLdepth z[], GLubyte mask[] ) +{ + /* switch cases ordered from most frequent to less frequent */ + switch (ctx->Depth.Func) { + case GL_LESS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] < zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] < zbuffer[i]) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_LEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] <= zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] <= zbuffer[i]) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] >= zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] >= zbuffer[i]) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_GREATER: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] > zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] > zbuffer[i]) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_NOTEQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] != zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] != zbuffer[i]) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_EQUAL: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] == zbuffer[i]) { + /* pass */ + zbuffer[i] = z[i]; + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + else { + /* Don't update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + if (z[i] == zbuffer[i]) { + /* pass */ + } + else { + /* fail */ + mask[i] = 0; + } + } + } + } + break; + case GL_ALWAYS: + if (ctx->Depth.Mask) { + /* Update Z buffer */ + GLuint i; + for (i=0; i<n; i++) { + if (mask[i]) { + zbuffer[i] = z[i]; + } + } + } + else { + /* Don't update Z buffer or mask */ + } + break; + case GL_NEVER: + /* depth test never passes */ + _mesa_bzero(mask, n * sizeof(GLubyte)); + break; + default: + _mesa_problem(ctx, "Bad depth func in hardware_depth_test_pixels"); + } +} + + + +static GLuint +depth_test_pixels( GLcontext *ctx, struct sw_span *span ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLuint n = span->end; + const GLint *x = span->array->x; + const GLint *y = span->array->y; + const GLdepth *z = span->array->z; + GLubyte *mask = span->array->mask; + + if (swrast->Driver.ReadDepthPixels) { + /* read depth values from hardware Z buffer */ + GLdepth zbuffer[MAX_WIDTH]; + (*swrast->Driver.ReadDepthPixels)(ctx, n, x, y, zbuffer); + + hardware_depth_test_pixels( ctx, n, zbuffer, z, mask ); + + /* update hardware Z buffer with new values */ + assert(swrast->Driver.WriteDepthPixels); + (*swrast->Driver.WriteDepthPixels)(ctx, n, x, y, zbuffer, mask ); + } + else { + /* software depth testing */ + if (ctx->Visual.depthBits <= 16) + software_depth_test_pixels16(ctx, n, x, y, z, mask); + else + software_depth_test_pixels32(ctx, n, x, y, z, mask); + } + return n; /* not really correct, but OK */ +} + + +/** + * Apply depth (Z) buffer testing to the span. + * \return approx number of pixels that passed (only zero is reliable) + */ +GLuint +_swrast_depth_test_span( GLcontext *ctx, struct sw_span *span) +{ + if (span->arrayMask & SPAN_XY) + return depth_test_pixels(ctx, span); + else + return depth_test_span(ctx, span); +} + + +/** + * GL_EXT_depth_bounds_test extension. + * Discard fragments depending on whether the corresponding Z-buffer + * values are outside the depth bounds test range. + * Note: we test the Z buffer values, not the fragment Z values! + * \return GL_TRUE if any fragments pass, GL_FALSE if no fragments pass + */ +GLboolean +_swrast_depth_bounds_test( GLcontext *ctx, struct sw_span *span ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + GLdepth zMin = (GLdepth) (ctx->Depth.BoundsMin * ctx->DepthMaxF + 0.5F); + GLdepth zMax = (GLdepth) (ctx->Depth.BoundsMax * ctx->DepthMaxF + 0.5F); + GLubyte *mask = span->array->mask; + GLuint i; + GLboolean anyPass = GL_FALSE; + + if (swrast->Driver.ReadDepthPixels) { + /* read depth values from hardware Z buffer */ + GLdepth zbuffer[MAX_WIDTH]; + ASSERT(span->end <= MAX_WIDTH); + if (span->arrayMask & SPAN_XY) + (*swrast->Driver.ReadDepthPixels)(ctx, span->end, span->array->x, + span->array->y, zbuffer); + else + (*swrast->Driver.ReadDepthSpan)(ctx, span->end, span->x, span->y, + zbuffer); + for (i = 0; i < span->end; i++) { + if (mask[i]) { + if (zbuffer[i] < zMin || zbuffer[i] > zMax) + mask[i] = GL_FALSE; + else + anyPass = GL_TRUE; + } + } + } + else { + /* software Z buffer */ + if (span->arrayMask & SPAN_XY) { + if (ctx->Visual.depthBits <= 16) { + /* 16 bits / Z */ + for (i = 0; i < span->end; i++) { + if (mask[i]) { + const GLushort *zPtr = Z_ADDRESS16(ctx, span->array->x[i], + span->array->y[i]); + if (*zPtr < zMin || *zPtr > zMax) + mask[i] = GL_FALSE; + else + anyPass = GL_TRUE; + } + } + } + else { + /* 32 bits / Z */ + for (i = 0; i < span->end; i++) { + if (mask[i]) { + const GLuint *zPtr = Z_ADDRESS32(ctx, span->array->x[i], + span->array->y[i]); + if (*zPtr < zMin || *zPtr > zMax) + mask[i] = GL_FALSE; + else + anyPass = GL_TRUE; + } + } + } + } + else { + if (ctx->Visual.depthBits <= 16) { + /* 16 bits / Z */ + const GLushort *zPtr = Z_ADDRESS16(ctx, span->x, span->y); + for (i = 0; i < span->end; i++) { + if (mask[i]) { + if (zPtr[i] < zMin || zPtr[i] > zMax) + mask[i] = GL_FALSE; + else + anyPass = GL_TRUE; + } + } + } + else { + /* 32 bits / Z */ + const GLuint *zPtr = Z_ADDRESS32(ctx, span->x, span->y); + for (i = 0; i < span->end; i++) { + if (mask[i]) { + if (zPtr[i] < zMin || zPtr[i] > zMax) + mask[i] = GL_FALSE; + else + anyPass = GL_TRUE; + } + } + } + } + } + return anyPass; +} + + + +/**********************************************************************/ +/***** Read Depth Buffer *****/ +/**********************************************************************/ + + +/** + * Read a span of depth values from the depth buffer. + * This function does clipping before calling the device driver function. + */ +void +_swrast_read_depth_span( GLcontext *ctx, + GLint n, GLint x, GLint y, GLdepth depth[] ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height || + x + (GLint) n <= 0 || x >= (GLint) 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 > (GLint) ctx->DrawBuffer->Width) { + GLint dx = x + n - (GLint) 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 ); + GLint i; + for (i = 0; i < n; i++) { + depth[i] = zptr[i]; + } + } + else { + const GLuint *zptr = Z_ADDRESS32( ctx, x, y ); + GLint i; + for (i = 0; i < n; i++) { + depth[i] = zptr[i]; + } + } + } + else if (swrast->Driver.ReadDepthSpan) { + /* read from hardware depth buffer */ + (*swrast->Driver.ReadDepthSpan)( ctx, n, x, y, depth ); + } + else { + /* no depth buffer */ + _mesa_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. + * Input: n - how many pixels + * x,y - location of first pixel + * Output: depth - the array of depth values + */ +void +_swrast_read_depth_span_float( GLcontext *ctx, + GLint n, GLint x, GLint y, GLfloat depth[] ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + const GLfloat scale = 1.0F / ctx->DepthMaxF; + + if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height || + x + (GLint) n <= 0 || x >= (GLint) 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 > (GLint) ctx->DrawBuffer->Width) { + GLint dx = x + n - (GLint) 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) { + const GLushort *zptr = Z_ADDRESS16( ctx, x, y ); + GLint i; + for (i = 0; i < n; i++) { + depth[i] = (GLfloat) zptr[i] * scale; + } + } + else { + const GLuint *zptr = Z_ADDRESS32( ctx, x, y ); + GLint i; + for (i = 0; i < n; i++) { + depth[i] = (GLfloat) zptr[i] * scale; + } + } + } + else if (swrast->Driver.ReadDepthSpan) { + /* read from hardware depth buffer */ + GLdepth d[MAX_WIDTH]; + GLint i; + assert(n <= MAX_WIDTH); + (*swrast->Driver.ReadDepthSpan)( ctx, n, x, y, d ); + for (i = 0; i < n; i++) { + depth[i] = d[i] * scale; + } + } + else { + /* no depth buffer */ + _mesa_bzero(depth, n * sizeof(GLfloat)); + } +} + + + +/**********************************************************************/ +/***** Allocate and Clear Depth Buffer *****/ +/**********************************************************************/ + + + +/** + * Allocate a new depth buffer. If there's already a depth buffer allocated + * it will be free()'d. The new depth buffer will be uniniitalized. + * This function is only called through Driver.alloc_depth_buffer. + */ +void +_swrast_alloc_depth_buffer( GLframebuffer *buffer ) +{ + GLint bytesPerValue; + + ASSERT(buffer->UseSoftwareDepthBuffer); + + /* deallocate current depth buffer if present */ + if (buffer->DepthBuffer) { + MESA_PBUFFER_FREE(buffer->DepthBuffer); + buffer->DepthBuffer = NULL; + } + + /* allocate new depth buffer, but don't initialize it */ + if (buffer->Visual.depthBits <= 16) + bytesPerValue = sizeof(GLushort); + else + bytesPerValue = sizeof(GLuint); + + buffer->DepthBuffer = MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height + * bytesPerValue); + + if (!buffer->DepthBuffer) { + /* out of memory */ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + ctx->Depth.Test = GL_FALSE; + ctx->NewState |= _NEW_DEPTH; + _mesa_error(ctx, GL_OUT_OF_MEMORY, "Couldn't allocate depth buffer"); + } + } +} + + +/** + * Clear the depth buffer. If the depth buffer doesn't exist yet we'll + * allocate it now. + * This function is only called through Driver.clear_depth_buffer. + */ +void +_swrast_clear_depth_buffer( GLcontext *ctx ) +{ + SWcontext *swrast = SWRAST_CONTEXT(ctx); + + if (ctx->Visual.depthBits == 0 + || !ctx->Depth.Mask) { + /* no depth buffer, or writing to it is disabled */ + return; + } + + if (swrast->Driver.WriteMonoDepthSpan) { + const GLdepth clearValue = (GLdepth)(ctx->Depth.Clear * ctx->DepthMax); + const GLint x = ctx->DrawBuffer->_Xmin; + const GLint y = ctx->DrawBuffer->_Ymin; + const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + const GLint width = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + GLint i; + + for (i = 0; i < height; i++) { + (*swrast->Driver.WriteMonoDepthSpan)( ctx, width, x, y + i, + clearValue, NULL ); + } + + return; + } + + if (!ctx->DrawBuffer->DepthBuffer) + return; + + /* The loops in this function have been written so the IRIX 5.3 + * C compiler can unroll them. Hopefully other compilers can too! + */ + + if (ctx->Scissor.Enabled) { + /* only clear scissor region */ + if (ctx->Visual.depthBits <= 16) { + const GLushort clearValue = (GLushort) (ctx->Depth.Clear * ctx->DepthMax); + const GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + const GLint cols = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + const GLint rowStride = ctx->DrawBuffer->Width; + GLushort *dRow = (GLushort *) ctx->DrawBuffer->DepthBuffer + + ctx->DrawBuffer->_Ymin * rowStride + ctx->DrawBuffer->_Xmin; + GLint i, j; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++) { + dRow[j] = clearValue; + } + dRow += rowStride; + } + } + else { + const GLuint clearValue = (GLuint) (ctx->Depth.Clear * ctx->DepthMax); + const GLint rows = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin; + const GLint cols = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin; + const GLint rowStride = ctx->DrawBuffer->Width; + GLuint *dRow = (GLuint *) ctx->DrawBuffer->DepthBuffer + + ctx->DrawBuffer->_Ymin * rowStride + ctx->DrawBuffer->_Xmin; + GLint i, j; + for (i = 0; i < rows; i++) { + for (j = 0; j < cols; j++) { + dRow[j] = clearValue; + } + dRow += rowStride; + } + } + } + else { + /* clear whole buffer */ + if (ctx->Visual.depthBits <= 16) { + const GLushort clearValue = (GLushort) (ctx->Depth.Clear * ctx->DepthMax); + if ((clearValue & 0xff) == (clearValue >> 8)) { + if (clearValue == 0) { + _mesa_bzero(ctx->DrawBuffer->DepthBuffer, + 2*ctx->DrawBuffer->Width*ctx->DrawBuffer->Height); + } + else { + /* lower and upper bytes of clear_value are same, use MEMSET */ + MEMSET( ctx->DrawBuffer->DepthBuffer, clearValue & 0xff, + 2 * ctx->DrawBuffer->Width * ctx->DrawBuffer->Height); + } + } + else { + GLushort *d = (GLushort *) ctx->DrawBuffer->DepthBuffer; + GLint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; + while (n >= 16) { + d[0] = clearValue; d[1] = clearValue; + d[2] = clearValue; d[3] = clearValue; + d[4] = clearValue; d[5] = clearValue; + d[6] = clearValue; d[7] = clearValue; + d[8] = clearValue; d[9] = clearValue; + d[10] = clearValue; d[11] = clearValue; + d[12] = clearValue; d[13] = clearValue; + d[14] = clearValue; d[15] = clearValue; + d += 16; + n -= 16; + } + while (n > 0) { + *d++ = clearValue; + n--; + } + } + } + else { + /* >16 bit depth buffer */ + const GLuint clearValue = (GLuint) (ctx->Depth.Clear * ctx->DepthMax); + if (clearValue == 0) { + _mesa_bzero(ctx->DrawBuffer->DepthBuffer, + ctx->DrawBuffer->Width*ctx->DrawBuffer->Height*sizeof(GLuint)); + } + else { + GLint n = ctx->DrawBuffer->Width * ctx->DrawBuffer->Height; + GLuint *d = (GLuint *) ctx->DrawBuffer->DepthBuffer; + while (n >= 16) { + d[0] = clearValue; d[1] = clearValue; + d[2] = clearValue; d[3] = clearValue; + d[4] = clearValue; d[5] = clearValue; + d[6] = clearValue; d[7] = clearValue; + d[8] = clearValue; d[9] = clearValue; + d[10] = clearValue; d[11] = clearValue; + d[12] = clearValue; d[13] = clearValue; + d[14] = clearValue; d[15] = clearValue; + d += 16; + n -= 16; + } + while (n > 0) { + *d++ = clearValue; + n--; + } + } + } + } +} |
