-/* $Id: s_depth.c,v 1.23 2002/08/07 00:45:07 brianp Exp $ */
-
/*
* Mesa 3-D graphics library
- * Version: 4.1
+ * Version: 6.5.1
*
- * Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2006 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"),
#include "glheader.h"
#include "context.h"
#include "macros.h"
-#include "mem.h"
+#include "imports.h"
+#include "fbobject.h"
#include "s_depth.h"
#include "s_context.h"
+#include "s_span.h"
/**
- * Return address of depth buffer value for given window coord.
- */
-GLvoid *
-_mesa_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.
+ * Do depth test for a horizontal span of fragments.
* 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[] )
+ GLushort zbuffer[], const GLuint z[], GLubyte mask[] )
{
GLuint passed = 0;
}
break;
case GL_NEVER:
- BZERO(mask, n * sizeof(GLubyte));
+ _mesa_bzero(mask, n * sizeof(GLubyte));
break;
default:
_mesa_problem(ctx, "Bad depth func in depth_test_span16");
static GLuint
depth_test_span32( GLcontext *ctx, GLuint n,
- GLuint zbuffer[], const GLdepth z[], GLubyte mask[] )
+ GLuint zbuffer[], const GLuint z[], GLubyte mask[] )
{
GLuint passed = 0;
}
break;
case GL_NEVER:
- BZERO(mask, n * sizeof(GLubyte));
+ _mesa_bzero(mask, n * sizeof(GLubyte));
break;
default:
_mesa_problem(ctx, "Bad depth func in depth_test_span32");
/*
- * Apply depth test to span of fragments. Hardware or software z buffer.
+ * Apply depth test to span of fragments.
*/
static GLuint
-depth_test_span( GLcontext *ctx, struct sw_span *span)
+depth_test_span( GLcontext *ctx, SWspan *span)
{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
const GLint x = span->x;
const GLint y = span->y;
- const GLuint n = span->end;
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLuint count = span->end;
+ const GLuint *zValues = span->array->z;
+ GLubyte *mask = span->array->mask;
+ GLuint passed;
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);
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ /* Directly access buffer */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort *zbuffer = (GLushort *) rb->GetPointer(ctx, rb, x, y);
+ passed = depth_test_span16(ctx, count, zbuffer, zValues, mask);
}
else {
- GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, x, y);
- passed = depth_test_span32(ctx, n, zptr, span->array->z, span->array->mask);
+ GLuint *zbuffer = (GLuint *) rb->GetPointer(ctx, rb, x, y);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ passed = depth_test_span32(ctx, count, zbuffer, zValues, mask);
}
-#if 1
- if (passed < span->end) {
- span->writeAll = GL_FALSE;
+ }
+ else {
+ /* read depth values from buffer, test, write back */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort zbuffer[MAX_WIDTH];
+ rb->GetRow(ctx, rb, count, x, y, zbuffer);
+ passed = depth_test_span16(ctx, count, zbuffer, zValues, mask );
+ rb->PutRow(ctx, rb, count, x, y, zbuffer, NULL);
}
-#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 --;
+ else {
+ GLuint zbuffer[MAX_WIDTH];
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ rb->GetRow(ctx, rb, count, x, y, zbuffer);
+ passed = depth_test_span32(ctx, count, zbuffer, zValues, mask );
+ rb->PutRow(ctx, rb, count, x, y, zbuffer, NULL);
}
-#endif
- return passed;
}
+
+ if (passed < count) {
+ span->writeAll = GL_FALSE;
+ }
+ return passed;
}
+#define Z_ADDRESS(X, Y) (zStart + (Y) * stride + (X))
+
/*
- * Do depth testing for an array of fragments using software Z buffer.
+ * Do depth testing for an array of fragments at assorted locations.
*/
static void
-software_depth_test_pixels16( GLcontext *ctx, GLuint n,
- const GLint x[], const GLint y[],
- const GLdepth z[], GLubyte mask[] )
+direct_depth_test_pixels16(GLcontext *ctx, GLushort *zStart, GLuint stride,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint z[], GLubyte mask[] )
{
/* switch cases ordered from most frequent to less frequent */
switch (ctx->Depth.Func) {
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] < *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] < *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] <= *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] <= *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] >= *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] >= *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] > *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] > *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] != *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] != *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] == *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] == *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLushort *zptr = Z_ADDRESS16(ctx,x[i],y[i]);
+ GLushort *zptr = Z_ADDRESS(x[i], y[i]);
*zptr = z[i];
}
}
break;
case GL_NEVER:
/* depth test never passes */
- BZERO(mask, n * sizeof(GLubyte));
+ _mesa_bzero(mask, n * sizeof(GLubyte));
break;
default:
- _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels");
+ _mesa_problem(ctx, "Bad depth func in direct_depth_test_pixels");
}
}
/*
- * Do depth testing for an array of fragments using software Z buffer.
+ * Do depth testing for an array of fragments with direct access to zbuffer.
*/
static void
-software_depth_test_pixels32( GLcontext *ctx, GLuint n,
- const GLint x[], const GLint y[],
- const GLdepth z[], GLubyte mask[] )
+direct_depth_test_pixels32(GLcontext *ctx, GLuint *zStart, GLuint stride,
+ GLuint n, const GLint x[], const GLint y[],
+ const GLuint z[], GLubyte mask[] )
{
/* switch cases ordered from most frequent to less frequent */
switch (ctx->Depth.Func) {
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] < *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] < *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] <= *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] <= *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] >= *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] >= *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] > *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] > *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] != *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] != *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] == *zptr) {
/* pass */
*zptr = z[i];
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
if (z[i] == *zptr) {
/* pass */
}
GLuint i;
for (i=0; i<n; i++) {
if (mask[i]) {
- GLuint *zptr = Z_ADDRESS32(ctx,x[i],y[i]);
+ GLuint *zptr = Z_ADDRESS(x[i], y[i]);
*zptr = z[i];
}
}
break;
case GL_NEVER:
/* depth test never passes */
- BZERO(mask, n * sizeof(GLubyte));
+ _mesa_bzero(mask, n * sizeof(GLubyte));
break;
default:
- _mesa_problem(ctx, "Bad depth func in software_depth_test_pixels");
+ _mesa_problem(ctx, "Bad depth func in direct_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 */
- 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 )
+depth_test_pixels( GLcontext *ctx, SWspan *span )
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
- const GLuint n = span->end;
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ const GLuint count = span->end;
const GLint *x = span->array->x;
const GLint *y = span->array->y;
- const GLdepth *z = span->array->z;
+ const GLuint *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 );
+ if (rb->GetPointer(ctx, rb, 0, 0)) {
+ /* Directly access values */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort *zStart = (GLushort *) rb->Data;
+ GLuint stride = rb->Width;
+ direct_depth_test_pixels16(ctx, zStart, stride, count, x, y, z, mask);
+ }
+ else {
+ GLuint *zStart = (GLuint *) rb->Data;
+ GLuint stride = rb->Width;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ direct_depth_test_pixels32(ctx, zStart, stride, count, x, y, z, 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);
+ /* read depth values from buffer, test, write back */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort zbuffer[MAX_WIDTH];
+ _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLushort));
+ depth_test_span16(ctx, count, zbuffer, z, mask );
+ rb->PutValues(ctx, rb, count, x, y, zbuffer, NULL);
+ }
+ else {
+ GLuint zbuffer[MAX_WIDTH];
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ _swrast_get_values(ctx, rb, count, x, y, zbuffer, sizeof(GLuint));
+ depth_test_span32(ctx, count, zbuffer, z, mask );
+ rb->PutValues(ctx, rb, count, x, y, zbuffer, NULL);
+ }
}
- return n; /* not really correct, but OK */
+
+ return count; /* not really correct, but OK */
}
* \return approx number of pixels that passed (only zero is reliable)
*/
GLuint
-_mesa_depth_test_span( GLcontext *ctx, struct sw_span *span)
+_swrast_depth_test_span( GLcontext *ctx, SWspan *span)
{
if (span->arrayMask & SPAN_XY)
return depth_test_pixels(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, SWspan *span )
+{
+ struct gl_framebuffer *fb = ctx->DrawBuffer;
+ struct gl_renderbuffer *rb = fb->_DepthBuffer;
+ GLuint zMin = (GLuint) (ctx->Depth.BoundsMin * fb->_DepthMaxF + 0.5F);
+ GLuint zMax = (GLuint) (ctx->Depth.BoundsMax * fb->_DepthMaxF + 0.5F);
+ GLubyte *mask = span->array->mask;
+ const GLuint count = span->end;
+ GLuint i;
+ GLboolean anyPass = GL_FALSE;
+
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ /* get 16-bit values */
+ GLushort zbuffer16[MAX_WIDTH], *zbuffer;
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, count, span->array->x, span->array->y,
+ zbuffer16, sizeof(GLushort));
+ zbuffer = zbuffer16;
+ }
+ else {
+ zbuffer = (GLushort*) rb->GetPointer(ctx, rb, span->x, span->y);
+ if (!zbuffer) {
+ rb->GetRow(ctx, rb, count, span->x, span->y, zbuffer16);
+ zbuffer = zbuffer16;
+ }
+ }
+ assert(zbuffer);
+
+ /* Now do the tests */
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ if (zbuffer[i] < zMin || zbuffer[i] > zMax)
+ mask[i] = GL_FALSE;
+ else
+ anyPass = GL_TRUE;
+ }
+ }
+ }
+ else {
+ /* get 32-bit values */
+ GLuint zbuffer32[MAX_WIDTH], *zbuffer;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ if (span->arrayMask & SPAN_XY) {
+ _swrast_get_values(ctx, rb, count, span->array->x, span->array->y,
+ zbuffer32, sizeof(GLuint));
+ zbuffer = zbuffer32;
+ }
+ else {
+ zbuffer = (GLuint*) rb->GetPointer(ctx, rb, span->x, span->y);
+ if (!zbuffer) {
+ rb->GetRow(ctx, rb, count, span->x, span->y, zbuffer32);
+ zbuffer = zbuffer32;
+ }
+ }
+ assert(zbuffer);
+
+ /* Now do the tests */
+ for (i = 0; i < count; i++) {
+ if (mask[i]) {
+ if (zbuffer[i] < zMin || zbuffer[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.
+ * Read a span of depth values from the given depth renderbuffer, returning
+ * the values as GLfloats.
+ * This function does clipping to prevent reading outside the depth buffer's
+ * bounds. Though the clipping is redundant when we're called from
+ * _swrast_ReadPixels.
*/
void
-_mesa_read_depth_span( GLcontext *ctx,
- GLint n, GLint x, GLint y, GLdepth depth[] )
+_swrast_read_depth_span_float( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLfloat depth[] )
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
+ const GLfloat scale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
- if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height ||
- x + (GLint) n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) {
+ if (!rb) {
+ /* really only doing this to prevent FP exceptions later */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ }
+
+ ASSERT(rb->_BaseFormat == GL_DEPTH_COMPONENT);
+
+ if (y < 0 || y >= (GLint) rb->Height ||
+ x + n <= 0 || x >= (GLint) rb->Width) {
/* span is completely outside framebuffer */
- GLint i;
- for (i = 0; i < n; i++)
- depth[i] = 0;
+ _mesa_bzero(depth, n * sizeof(GLfloat));
return;
}
GLint dx = -x;
GLint i;
for (i = 0; i < dx; i++)
- depth[i] = 0;
+ depth[i] = 0.0;
x = 0;
n -= dx;
depth += dx;
}
- if (x + n > (GLint) ctx->DrawBuffer->Width) {
- GLint dx = x + n - (GLint) ctx->DrawBuffer->Width;
+ if (x + n > (GLint) rb->Width) {
+ GLint dx = x + n - (GLint) rb->Width;
GLint i;
for (i = 0; i < dx; i++)
- depth[n - i - 1] = 0;
+ depth[n - i - 1] = 0.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];
- }
+ if (rb->DataType == GL_UNSIGNED_INT) {
+ GLuint temp[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, n, x, y, temp);
+ for (i = 0; i < n; i++) {
+ depth[i] = temp[i] * scale;
}
}
- else if (swrast->Driver.ReadDepthSpan) {
- /* read from hardware depth buffer */
- (*swrast->Driver.ReadDepthSpan)( ctx, n, x, y, depth );
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort temp[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, n, x, y, temp);
+ for (i = 0; i < n; i++) {
+ depth[i] = temp[i] * scale;
+ }
}
else {
- /* no depth buffer */
- BZERO(depth, n * sizeof(GLfloat));
+ _mesa_problem(ctx, "Invalid depth renderbuffer data type");
}
-
}
-
-
/**
- * 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
+ * As above, but return 32-bit GLuint values.
*/
void
-_mesa_read_depth_span_float( GLcontext *ctx,
- GLint n, GLint x, GLint y, GLfloat depth[] )
+_swrast_read_depth_span_uint( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLuint depth[] )
{
- SWcontext *swrast = SWRAST_CONTEXT(ctx);
- const GLfloat scale = 1.0F / ctx->DepthMaxF;
+ if (!rb) {
+ /* really only doing this to prevent FP exceptions later */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ }
- if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height ||
- x + (GLint) n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) {
+ ASSERT(rb->_BaseFormat == GL_DEPTH_COMPONENT);
+
+ if (y < 0 || y >= (GLint) rb->Height ||
+ x + n <= 0 || x >= (GLint) rb->Width) {
/* span is completely outside framebuffer */
- GLint i;
- for (i = 0; i < n; i++)
- depth[i] = 0.0F;
+ _mesa_bzero(depth, n * sizeof(GLfloat));
return;
}
GLint dx = -x;
GLint i;
for (i = 0; i < dx; i++)
- depth[i] = 0.0F;
- n -= dx;
+ depth[i] = 0;
x = 0;
+ n -= dx;
+ depth += dx;
}
- if (x + n > (GLint) ctx->DrawBuffer->Width) {
- GLint dx = x + n - (GLint) ctx->DrawBuffer->Width;
+ if (x + n > (GLint) rb->Width) {
+ GLint dx = x + n - (GLint) rb->Width;
GLint i;
for (i = 0; i < dx; i++)
- depth[n - i - 1] = 0.0F;
+ 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 );
+ if (rb->DataType == GL_UNSIGNED_INT) {
+ rb->GetRow(ctx, rb, n, x, y, depth);
+ if (rb->DepthBits < 32) {
+ GLuint shift = 32 - rb->DepthBits;
GLint i;
for (i = 0; i < n; i++) {
- depth[i] = (GLfloat) zptr[i] * scale;
+ GLuint z = depth[i];
+ depth[i] = z << shift; /* XXX lsb bits? */
}
}
- else {
- const GLuint *zptr = Z_ADDRESS32( ctx, x, y );
- GLint i;
+ }
+ else if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort temp[MAX_WIDTH];
+ GLint i;
+ rb->GetRow(ctx, rb, n, x, y, temp);
+ if (rb->DepthBits == 16) {
for (i = 0; i < n; i++) {
- depth[i] = (GLfloat) zptr[i] * scale;
+ GLuint z = temp[i];
+ depth[i] = (z << 16) | z;
}
}
- }
- 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 {
+ GLuint shift = 16 - rb->DepthBits;
+ for (i = 0; i < n; i++) {
+ GLuint z = temp[i];
+ depth[i] = (z << (shift + 16)) | (z << shift); /* XXX lsb bits? */
+ }
}
}
else {
- /* no depth buffer */
- BZERO(depth, n * sizeof(GLfloat));
+ _mesa_problem(ctx, "Invalid depth renderbuffer data type");
}
}
-/**********************************************************************/
-/***** 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.
+ * Clear the given z/depth renderbuffer.
*/
void
-_mesa_alloc_depth_buffer( GLframebuffer *buffer )
+_swrast_clear_depth_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
{
- GLint bytesPerValue;
-
- ASSERT(buffer->UseSoftwareDepthBuffer);
+ GLuint clearValue;
+ GLint x, y, width, height;
- /* 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
-_mesa_clear_depth_buffer( GLcontext *ctx )
-{
- if (ctx->Visual.depthBits == 0
- || !ctx->DrawBuffer->DepthBuffer
- || !ctx->Depth.Mask) {
+ if (!rb || !ctx->Depth.Mask) {
/* no depth buffer, or writing to it is disabled */
return;
}
- /* The loops in this function have been written so the IRIX 5.3
- * C compiler can unroll them. Hopefully other compilers can too!
- */
+ /* compute integer clearing value */
+ if (ctx->Depth.Clear == 1.0) {
+ clearValue = ctx->DrawBuffer->_DepthMax;
+ }
+ else {
+ clearValue = (GLuint) (ctx->Depth.Clear * ctx->DrawBuffer->_DepthMaxF);
+ }
- 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;
+ assert(rb->_BaseFormat == GL_DEPTH_COMPONENT);
+
+ /* 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 is possible. Either this is just malloc'd
+ * memory, or perhaps the driver mmap'd the zbuffer memory.
+ */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ if ((clearValue & 0xff) == ((clearValue >> 8) & 0xff) &&
+ ((GLushort *) rb->GetPointer(ctx, rb, 0, 0) + width ==
+ (GLushort *) rb->GetPointer(ctx, rb, 0, 1))) {
+ /* optimized case */
+ GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y);
+ GLuint len = width * height * sizeof(GLushort);
+ _mesa_memset(dst, (clearValue & 0xff), len);
+ }
+ else {
+ /* general case */
+ GLint i, j;
+ for (i = 0; i < height; i++) {
+ GLushort *dst = (GLushort *) rb->GetPointer(ctx, rb, x, y + i);
+ for (j = 0; j < width; j++) {
+ dst[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;
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ for (i = 0; i < height; i++) {
+ GLuint *dst = (GLuint *) rb->GetPointer(ctx, rb, x, y + i);
+ for (j = 0; j < width; j++) {
+ dst[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) {
- 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);
- }
+ /* Direct access not possible. Use PutRow to write new values. */
+ if (rb->DataType == GL_UNSIGNED_SHORT) {
+ GLushort clearVal16 = (GLushort) (clearValue & 0xffff);
+ GLint i;
+ for (i = 0; i < height; i++) {
+ rb->PutMonoRow(ctx, rb, width, x, y + i, &clearVal16, NULL);
}
- 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 if (rb->DataType == GL_UNSIGNED_INT) {
+ GLint i;
+ ASSERT(sizeof(clearValue) == sizeof(GLuint));
+ for (i = 0; i < height; i++) {
+ rb->PutMonoRow(ctx, rb, width, x, y + i, &clearValue, NULL);
}
}
else {
- /* >16 bit depth buffer */
- const GLuint clearValue = (GLuint) (ctx->Depth.Clear * ctx->DepthMax);
- if (clearValue == 0) {
- 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--;
- }
- }
+ _mesa_problem(ctx, "bad depth renderbuffer DataType");
}
}
}