Mesa (mesa_7_7_branch): swrast: fix broken _swrast_depth_clamp_span()

Brian Paul brianp at kemper.freedesktop.org
Fri Jan 15 21:23:32 UTC 2010


Module: Mesa
Branch: mesa_7_7_branch
Commit: 73856817973caab283427c52152672f524c49a07
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=73856817973caab283427c52152672f524c49a07

Author: Brian Paul <brianp at vmware.com>
Date:   Fri Jan 15 14:19:23 2010 -0700

swrast: fix broken _swrast_depth_clamp_span()

The integer Z clamping range depends on the number of bits
in the Z buffer because that's the scale factor used when we
transform NDC coords by the viewport/depth range.

Fixes fd.o bug #25972 but only for Z buffers up to a depth
of 30 bits.  Beyond that we get into messy integer overflow
issues and things fall apart.

---

 src/mesa/swrast/s_depth.c |   41 +++++++++++++++++++++++++++--------------
 1 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/src/mesa/swrast/s_depth.c b/src/mesa/swrast/s_depth.c
index 0b6bb7e..ac5dae2 100644
--- a/src/mesa/swrast/s_depth.c
+++ b/src/mesa/swrast/s_depth.c
@@ -497,17 +497,24 @@ depth_test_span32( GLcontext *ctx, GLuint n,
    return passed;
 }
 
-/* Apply ARB_depth_clamp to span of fragments. */
+
+
+/**
+ * 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;
-   struct gl_renderbuffer *rb = fb->_DepthBuffer;
    const GLuint count = span->end;
-   GLuint *zValues = span->array->z;
-   GLuint min, max;
+   GLint *zValues = (GLint *) span->array->z; /* sign change */
+   GLint min, max;
    GLfloat min_f, max_f;
-   int i;
+   GLuint i;
 
    if (ctx->Viewport.Near < ctx->Viewport.Far) {
       min_f = ctx->Viewport.Near;
@@ -517,15 +524,21 @@ _swrast_depth_clamp_span( GLcontext *ctx, SWspan *span )
       max_f = ctx->Viewport.Near;
    }
 
-   if (rb->DataType == GL_UNSIGNED_SHORT) {
-      CLAMPED_FLOAT_TO_USHORT(min, min_f);
-      CLAMPED_FLOAT_TO_USHORT(max, max_f);
-   } else {
-      assert(rb->DataType == GL_UNSIGNED_INT);
-      min = FLOAT_TO_UINT(min_f);
-      max = FLOAT_TO_UINT(max_f);
-   }
-
+   /* 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;




More information about the mesa-commit mailing list