aboutsummaryrefslogtreecommitdiff
path: root/mesalib/src/mesa/swrast/s_depth.c
diff options
context:
space:
mode:
Diffstat (limited to 'mesalib/src/mesa/swrast/s_depth.c')
-rw-r--r--mesalib/src/mesa/swrast/s_depth.c1429
1 files changed, 1429 insertions, 0 deletions
diff --git a/mesalib/src/mesa/swrast/s_depth.c b/mesalib/src/mesa/swrast/s_depth.c
new file mode 100644
index 000000000..26e23f02d
--- /dev/null
+++ b/mesalib/src/mesa/swrast/s_depth.c
@@ -0,0 +1,1429 @@
+/*
+ * Mesa 3-D graphics library
+ * Version: 7.2.1
+ *
+ * Copyright (C) 1999-2008 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 "main/glheader.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/fbobject.h"
+
+#include "s_depth.h"
+#include "s_context.h"
+#include "s_span.h"
+
+
+/**
+ * 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 GLuint 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 GLuint 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.
+ */
+static GLuint
+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 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 (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 *zbuffer = (GLuint *) rb->GetPointer(ctx, rb, x, y);
+ ASSERT(rb->DataType == GL_UNSIGNED_INT);
+ passed = depth_test_span32(ctx, count, zbuffer, zValues, mask);
+ }
+ }
+ 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, mask);
+ }
+ 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, mask);
+ }
+ }
+
+ 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 at assorted locations.
+ */
+static void
+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) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLushort *zptr = Z_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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 direct_depth_test_pixels");
+ }
+}
+
+
+
+/*
+ * Do depth testing for an array of fragments with direct access to zbuffer.
+ */
+static void
+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) {
+ case GL_LESS:
+ if (ctx->Depth.Mask) {
+ /* Update Z buffer */
+ GLuint i;
+ for (i=0; i<n; i++) {
+ if (mask[i]) {
+ GLuint *zptr = Z_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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_ADDRESS(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 direct_depth_test_pixels");
+ }
+}
+
+
+
+
+static GLuint
+depth_test_pixels( GLcontext *ctx, SWspan *span )
+{
+ 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 GLuint *z = span->array->z;
+ GLubyte *mask = span->array->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 {
+ /* 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, mask);
+ }
+ 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, mask);
+ }
+ }
+
+ return count; /* 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, SWspan *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, 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 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
+_swrast_read_depth_span_float( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLfloat depth[] )
+{
+ const GLfloat scale = 1.0F / ctx->DrawBuffer->_DepthMaxF;
+
+ 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 */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ return;
+ }
+
+ if (x < 0) {
+ GLint dx = -x;
+ GLint i;
+ for (i = 0; i < dx; i++)
+ depth[i] = 0.0;
+ x = 0;
+ n -= dx;
+ depth += dx;
+ }
+ 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.0;
+ n -= dx;
+ }
+ if (n <= 0) {
+ return;
+ }
+
+ 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 (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 {
+ _mesa_problem(ctx, "Invalid depth renderbuffer data type");
+ }
+}
+
+
+/**
+ * As above, but return 32-bit GLuint values.
+ */
+void
+_swrast_read_depth_span_uint( GLcontext *ctx, struct gl_renderbuffer *rb,
+ GLint n, GLint x, GLint y, GLuint depth[] )
+{
+ 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 */
+ _mesa_bzero(depth, n * sizeof(GLfloat));
+ 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) rb->Width) {
+ GLint dx = x + n - (GLint) rb->Width;
+ GLint i;
+ for (i = 0; i < dx; i++)
+ depth[n - i - 1] = 0;
+ n -= dx;
+ }
+ if (n <= 0) {
+ return;
+ }
+
+ 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++) {
+ GLuint z = depth[i];
+ depth[i] = z << shift; /* XXX lsb bits? */
+ }
+ }
+ }
+ 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++) {
+ GLuint z = temp[i];
+ depth[i] = (z << 16) | z;
+ }
+ }
+ 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 {
+ _mesa_problem(ctx, "Invalid depth renderbuffer data type");
+ }
+}
+
+
+
+/**
+ * Clear the given z/depth renderbuffer.
+ */
+void
+_swrast_clear_depth_buffer( GLcontext *ctx, struct gl_renderbuffer *rb )
+{
+ GLuint clearValue;
+ GLint x, y, width, height;
+
+ if (!rb || !ctx->Depth.Mask) {
+ /* no depth buffer, or writing to it is disabled */
+ return;
+ }
+
+ /* compute integer clearing value */
+ if (ctx->Depth.Clear == 1.0) {
+ clearValue = ctx->DrawBuffer->_DepthMax;
+ }
+ else {
+ clearValue = (GLuint) (ctx->Depth.Clear * ctx->DrawBuffer->_DepthMaxF);
+ }
+
+ 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;
+ }
+ }
+ }
+ }
+ else {
+ GLint i, j;
+ 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;
+ }
+ }
+ }
+ }
+ else {
+ /* 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 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 {
+ _mesa_problem(ctx, "bad depth renderbuffer DataType");
+ }
+ }
+}