Do depth testing with integer values.
authorBrian <brian.paul@tungstengraphics.com>
Tue, 10 Jul 2007 19:53:21 +0000 (13:53 -0600)
committerBrian <brian.paul@tungstengraphics.com>
Tue, 10 Jul 2007 19:53:21 +0000 (13:53 -0600)
Using floats (and float->ushort->float conversion) introduces errors.
Only GLushort depth buffers work for now...

src/mesa/drivers/x11/xm_surface.c
src/mesa/pipe/softpipe/sp_quad_depth_test.c
src/mesa/pipe/softpipe/sp_surface.h

index 30c9049..5158e42 100644 (file)
@@ -43,6 +43,7 @@
 #include "renderbuffer.h"
 
 #include "pipe/p_state.h"
+#include "pipe/p_defines.h"
 #include "pipe/softpipe/sp_context.h"
 #include "pipe/softpipe/sp_surface.h"
 
@@ -245,7 +246,7 @@ xmesa_get_color_surface(GLcontext *ctx, GLuint buf)
 
 static void
 read_quad_z(struct softpipe_surface *sps,
-            GLint x, GLint y, GLfloat zzzz[QUAD_SIZE])
+            GLint x, GLint y, GLuint zzzz[QUAD_SIZE])
 {
    struct xmesa_surface *xmsurf = xmesa_surface(sps);
    struct gl_renderbuffer *rb = xmsurf->rb;
@@ -254,22 +255,24 @@ read_quad_z(struct softpipe_surface *sps,
    GET_CURRENT_CONTEXT(ctx);
    rb->GetRow(ctx, rb, 2, x, y,     temp);
    rb->GetRow(ctx, rb, 2, x, y + 1, temp + 2);
+   /* convert from GLushort to GLuint */
    for (i = 0; i < 4; i++) {
-      zzzz[i] = USHORT_TO_FLOAT(temp[i]);
+      zzzz[i] = temp[i];
    }
 }
 
 static void
 write_quad_z(struct softpipe_surface *sps,
-             GLint x, GLint y, const GLfloat zzzz[QUAD_SIZE])
+             GLint x, GLint y, const GLuint zzzz[QUAD_SIZE])
 {
    struct xmesa_surface *xmsurf = xmesa_surface(sps);
    struct gl_renderbuffer *rb = xmsurf->rb;
    GLushort temp[4];
    GLuint i;
    GET_CURRENT_CONTEXT(ctx);
+   /* convert from GLuint to GLushort */
    for (i = 0; i < 4; i++) {
-      CLAMPED_FLOAT_TO_USHORT(temp[i], zzzz[i]);
+      temp[i] = zzzz[i];
    }
    rb->PutRow(ctx, rb, 2, x, y,     temp,     NULL);
    rb->PutRow(ctx, rb, 2, x, y + 1, temp + 2, NULL);
@@ -283,6 +286,7 @@ create_z_surface(XMesaContext xmctx, struct gl_renderbuffer *rb)
 
    xmsurf = CALLOC_STRUCT(xmesa_surface);
    if (xmsurf) {
+      xmsurf->sps.surface.format = PIPE_FORMAT_U_Z16;
       xmsurf->sps.surface.width = rb->Width;
       xmsurf->sps.surface.height = rb->Height;
       xmsurf->sps.read_quad_z = read_quad_z;
index fcd6a22..0b5d909 100644 (file)
@@ -39,15 +39,38 @@ static void
 depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
 {
    struct softpipe_context *softpipe = qs->softpipe;
-   GLuint j;
    struct softpipe_surface *sps = softpipe_surface(softpipe->framebuffer.zbuf);
-   GLfloat zzzz[QUAD_SIZE];  /**< Z for four pixels in quad */
+   GLuint bzzzz[QUAD_SIZE];  /**< Z values fetched from depth buffer */
+   GLuint qzzzz[QUAD_SIZE];  /**< Z values from the quad */
    GLuint zmask = 0;
+   GLuint j;
+   GLfloat scale;
 
    assert(sps); /* shouldn't get here if there's no zbuffer */
 
+   /*
+    * To increase efficiency, we should probably have multiple versions
+    * of this function that are specifically for Z16, Z32 and FP Z buffers.
+    * Try to effectively do that with codegen...
+    */
+   if (sps->surface.format == PIPE_FORMAT_U_Z16)
+      scale = 65535.0;
+   else
+      assert(0);  /* XXX fix this someday */
+
+   /*
+    * Convert quad's float depth values to int depth values.
+    * If the Z buffer stores integer values, we _have_ to do the depth
+    * compares with integers (not floats).  Otherwise, the float->int->float
+    * conversion of Z values (which isn't an identity function) will cause
+    * Z-fighting errors.
+    */
+   for (j = 0; j < QUAD_SIZE; j++) {
+      qzzzz[j] = (GLuint) (quad->outputs.depth[j] * scale);
+   }
+
    /* get zquad from zbuffer */
-   sps->read_quad_z(sps, quad->x0, quad->y0, zzzz);
+   sps->read_quad_z(sps, quad->x0, quad->y0, bzzzz);
 
    switch (softpipe->depth_test.func) {
    case PIPE_FUNC_NEVER:
@@ -57,19 +80,19 @@ depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
        * Like this:  quad->mask &= (quad->outputs.depth < zzzz);
        */
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (quad->outputs.depth[j] < zzzz[j]) 
+        if (qzzzz[j] < bzzzz[j]) 
            zmask |= 1 << j;
       }
       break;
    case PIPE_FUNC_EQUAL:
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (quad->outputs.depth[j] == zzzz[j]) 
+        if (qzzzz[j] == bzzzz[j]) 
            zmask |= 1 << j;
       }
       break;
    case PIPE_FUNC_LEQUAL:
       for (j = 0; j < QUAD_SIZE; j++) {
-        if (quad->outputs.depth[j] <= zzzz[j]) 
+        if (qzzzz[j] <= bzzzz[j]) 
            zmask |= (1 << j);
       }
       break;
@@ -86,12 +109,12 @@ depth_test_quad(struct quad_stage *qs, struct quad_header *quad)
        */
       for (j = 0; j < QUAD_SIZE; j++) {
         if (quad->mask & (1 << j)) {
-           zzzz[j] = quad->outputs.depth[j];
+           bzzzz[j] = qzzzz[j];
         }
       }
 
       /* write updated zquad to zbuffer */
-      sps->write_quad_z(sps, quad->x0, quad->y0, zzzz);
+      sps->write_quad_z(sps, quad->x0, quad->y0, bzzzz);
    }
 
    qs->next->run(qs->next, quad);
index ac66ffe..450542a 100644 (file)
@@ -79,9 +79,9 @@ struct softpipe_surface {
                               GLubyte rgba[NUM_CHANNELS] );
 
    void (*read_quad_z)(struct softpipe_surface *,
-                       GLint x, GLint y, GLfloat zzzz[QUAD_SIZE]);
+                       GLint x, GLint y, GLuint zzzz[QUAD_SIZE]);
    void (*write_quad_z)(struct softpipe_surface *,
-                        GLint x, GLint y, const GLfloat zzzz[QUAD_SIZE]);
+                        GLint x, GLint y, const GLuint zzzz[QUAD_SIZE]);
 };