swrast: fix broken _swrast_depth_clamp_span()
[mesa.git] / src / mesa / swrast / s_depth.c
index 293eb8628e619972c9b978163f371b710b74685b..ac5dae2148b4e8e3cc6f2fcac44ae9bbfb96b1f1 100644 (file)
@@ -1,8 +1,8 @@
 /*
  * Mesa 3-D graphics library
- * Version:  6.5.1
+ * Version:  7.2.1
  *
- * Copyright (C) 1999-2006  Brian Paul   All Rights Reserved.
+ * 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"),
@@ -25,9 +25,9 @@
 
 #include "main/glheader.h"
 #include "main/context.h"
+#include "main/formats.h"
 #include "main/macros.h"
 #include "main/imports.h"
-#include "main/fbobject.h"
 
 #include "s_depth.h"
 #include "s_context.h"
@@ -499,6 +499,56 @@ depth_test_span32( GLcontext *ctx, GLuint n,
 
 
 
+/**
+ * Clamp fragment Z values to the depth near/far range (glDepthRange()).
+ * This is used when GL_ARB_depth_clamp/GL_DEPTH_CLAMP is turned on.
+ * In that case, vertexes are not clipped against the near/far planes
+ * so rasterization will produce fragment Z values outside the usual
+ * [0,1] range.
+ */
+void
+_swrast_depth_clamp_span( GLcontext *ctx, SWspan *span )
+{
+   struct gl_framebuffer *fb = ctx->DrawBuffer;
+   const GLuint count = span->end;
+   GLint *zValues = (GLint *) span->array->z; /* sign change */
+   GLint min, max;
+   GLfloat min_f, max_f;
+   GLuint i;
+
+   if (ctx->Viewport.Near < ctx->Viewport.Far) {
+      min_f = ctx->Viewport.Near;
+      max_f = ctx->Viewport.Far;
+   } else {
+      min_f = ctx->Viewport.Far;
+      max_f = ctx->Viewport.Near;
+   }
+
+   /* Convert floating point values in [0,1] to device Z coordinates in
+    * [0, DepthMax].
+    * ex: If the the Z buffer has 24 bits, DepthMax = 0xffffff.
+    * 
+    * XXX this all falls apart if we have 31 or more bits of Z because
+    * the triangle rasterization code produces unsigned Z values.  Negative
+    * vertex Z values come out as large fragment Z uints.
+    */
+   min = (GLint) (min_f * fb->_DepthMaxF);
+   max = (GLint) (max_f * fb->_DepthMaxF);
+   if (max < 0)
+      max = 0x7fffffff; /* catch over flow for 30-bit z */
+
+   /* Note that we do the comparisons here using signed integers.
+    */
+   for (i = 0; i < count; i++) {
+      if (zValues[i] < min)
+        zValues[i] = min;
+      if (zValues[i] > max)
+        zValues[i] = max;
+   }
+}
+
+
+
 /*
  * Apply depth test to span of fragments.
  */
@@ -534,15 +584,15 @@ depth_test_span( GLcontext *ctx, SWspan *span)
       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);
+         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, NULL);
+         passed = depth_test_span32(ctx, count, zbuffer, zValues, mask);
+         rb->PutRow(ctx, rb, count, x, y, zbuffer, mask);
       }
    }
 
@@ -1080,15 +1130,15 @@ depth_test_pixels( GLcontext *ctx, SWspan *span )
       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);
+         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, NULL);
+         depth_test_span32(ctx, count, zbuffer, z, mask);
+         rb->PutValues(ctx, rb, count, x, y, zbuffer, mask);
       }
    }
 
@@ -1211,6 +1261,7 @@ _swrast_read_depth_span_float( GLcontext *ctx, struct gl_renderbuffer *rb,
    if (!rb) {
       /* really only doing this to prevent FP exceptions later */
       _mesa_bzero(depth, n * sizeof(GLfloat));
+      return;
    }
 
    ASSERT(rb->_BaseFormat == GL_DEPTH_COMPONENT);
@@ -1271,11 +1322,16 @@ void
 _swrast_read_depth_span_uint( GLcontext *ctx, struct gl_renderbuffer *rb,
                               GLint n, GLint x, GLint y, GLuint depth[] )
 {
+   GLuint depthBits;
+
    if (!rb) {
       /* really only doing this to prevent FP exceptions later */
-      _mesa_bzero(depth, n * sizeof(GLfloat));
+      _mesa_bzero(depth, n * sizeof(GLuint));
+      return;
    }
 
+   depthBits = _mesa_get_format_bits(rb->Format, GL_DEPTH_BITS);
+
    ASSERT(rb->_BaseFormat == GL_DEPTH_COMPONENT);
 
    if (y < 0 || y >= (GLint) rb->Height ||
@@ -1307,8 +1363,8 @@ _swrast_read_depth_span_uint( GLcontext *ctx, struct gl_renderbuffer *rb,
 
    if (rb->DataType == GL_UNSIGNED_INT) {
       rb->GetRow(ctx, rb, n, x, y, depth);
-      if (rb->DepthBits < 32) {
-         GLuint shift = 32 - rb->DepthBits;
+      if (depthBits < 32) {
+         GLuint shift = 32 - depthBits;
          GLint i;
          for (i = 0; i < n; i++) {
             GLuint z = depth[i];
@@ -1320,14 +1376,14 @@ _swrast_read_depth_span_uint( GLcontext *ctx, struct gl_renderbuffer *rb,
       GLushort temp[MAX_WIDTH];
       GLint i;
       rb->GetRow(ctx, rb, n, x, y, temp);
-      if (rb->DepthBits == 16) {
+      if (depthBits == 16) {
          for (i = 0; i < n; i++) {
             GLuint z = temp[i];
             depth[i] = (z << 16) | z;
          }
       }
       else {
-         GLuint shift = 16 - rb->DepthBits;
+         GLuint shift = 16 - depthBits;
          for (i = 0; i < n; i++) {
             GLuint z = temp[i];
             depth[i] = (z << (shift + 16)) | (z << shift); /* XXX lsb bits? */