*** empty log message ***
[mesa.git] / src / mesa / swrast / s_depth.c
index 1962dbef78c0fa1802a77da41540748ebb35b0c8..34897ba931b17bf6c7b048e44ec8f9b2dcbb46ea 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: s_depth.c,v 1.13 2002/01/28 00:07:33 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  4.1
+ * Version:  5.1
  *
- * Copyright (C) 1999-2002  Brian Paul   All Rights Reserved.
+ * Copyright (C) 1999-2003  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 "s_depth.h"
 #include "s_context.h"
-#include "s_pb.h"
-
 
 
-
-/*
+/**
  * Return address of depth buffer value for given window coord.
  */
 GLvoid *
-_mesa_zbuffer_address(GLcontext *ctx, GLint x, GLint y)
+_swrast_zbuffer_address(GLcontext *ctx, GLint x, GLint y)
 {
    if (ctx->Visual.depthBits <= 16)
-      return (GLushort *) ctx->DrawBuffer->DepthBuffer + ctx->DrawBuffer->Width * y + x;
+      return (GLushort *) ctx->DrawBuffer->DepthBuffer
+         + ctx->DrawBuffer->Width * y + x;
    else
-      return (GLuint *) ctx->DrawBuffer->DepthBuffer + ctx->DrawBuffer->Width * y + x;
+      return (GLuint *) ctx->DrawBuffer->DepthBuffer
+         + ctx->DrawBuffer->Width * y + x;
 }
 
 
@@ -73,7 +70,7 @@ _mesa_zbuffer_address(GLcontext *ctx, GLint x, GLint y)
  * Return:  number of fragments which pass the test.
  */
 static GLuint
-depth_test_span16( GLcontext *ctx, GLuint n, GLint x, GLint y,
+depth_test_span16( GLcontext *ctx, GLuint n,
                    GLushort zbuffer[], const GLdepth z[], GLubyte mask[] )
 {
    GLuint passed = 0;
@@ -291,7 +288,7 @@ depth_test_span16( GLcontext *ctx, GLuint n, GLint x, GLint y,
         }
         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");
@@ -302,7 +299,7 @@ depth_test_span16( GLcontext *ctx, GLuint n, GLint x, GLint y,
 
 
 static GLuint
-depth_test_span32( GLcontext *ctx, GLuint n, GLint x, GLint y,
+depth_test_span32( GLcontext *ctx, GLuint n,
                    GLuint zbuffer[], const GLdepth z[], GLubyte mask[] )
 {
    GLuint passed = 0;
@@ -520,7 +517,7 @@ depth_test_span32( GLcontext *ctx, GLuint n, GLint x, GLint y,
         }
         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");
@@ -534,56 +531,28 @@ depth_test_span32( GLcontext *ctx, GLuint n, GLint x, GLint y,
 /*
  * Apply depth test to span of fragments.  Hardware or software z buffer.
  */
-GLuint
-_old_depth_test_span( GLcontext *ctx, GLuint n, GLint x, GLint y,
-                     const GLdepth z[], GLubyte mask[] )
-{
-   SWcontext *swrast = SWRAST_CONTEXT(ctx);
-   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, x, y, zbuffer, z, mask);
-      assert(swrast->Driver.WriteDepthSpan);
-      (*swrast->Driver.WriteDepthSpan)(ctx, n, x, y, zbuffer, mask);
-      return passed;
-   }
-   else {
-      /* software depth buffer */
-      if (ctx->Visual.depthBits <= 16) {
-         GLushort *zptr = (GLushort *) Z_ADDRESS16(ctx, x, y);
-         GLuint passed = depth_test_span16(ctx, n, x, y, zptr, z, mask);
-         return passed;
-      }
-      else {
-         GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, x, y);
-         GLuint passed = depth_test_span32(ctx, n, x, y, zptr, z, mask);
-         return passed;
-      }
-   }
-}
-
-/*
- * Apply depth test to span of fragments.  Hardware or software z buffer.
- */
-GLuint
-_mesa_depth_test_span( GLcontext *ctx, struct sw_span *span)
+static GLuint
+depth_test_span( GLcontext *ctx, struct sw_span *span)
 {
+   const GLint x = span->x;
+   const GLint y = span->y;
+   const GLuint n = span->end;
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
+   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, span->end, span->x, span->y, zbuffer);
-      passed = depth_test_span32(ctx, span->end, span->x, span->y,
-                                zbuffer, span->zArray, span->mask);
+      (*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, span->end, span->x, span->y, zbuffer, span->mask);
-      if (passed < span->end)
+      (*swrast->Driver.WriteDepthSpan)(ctx, n, x, y, zbuffer,
+                                       span->array->mask);
+      if (passed < n)
          span->writeAll = GL_FALSE;
       return passed;
    }
@@ -591,15 +560,29 @@ _mesa_depth_test_span( GLcontext *ctx, struct sw_span *span)
       GLuint passed;
       /* software depth buffer */
       if (ctx->Visual.depthBits <= 16) {
-         GLushort *zptr = (GLushort *) Z_ADDRESS16(ctx, span->x, span->y);
-         passed = depth_test_span16(ctx, span->end, span->x, span->y, zptr, span->zArray, span->mask);
+         GLushort *zptr = (GLushort *) Z_ADDRESS16(ctx, x, y);
+         passed = depth_test_span16(ctx, n, zptr, span->array->z, span->array->mask);
       }
       else {
-         GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, span->x, span->y);
-         passed = depth_test_span32(ctx, span->end, span->x, span->y, zptr, span->zArray, span->mask);
+         GLuint *zptr = (GLuint *) Z_ADDRESS32(ctx, x, y);
+         passed = depth_test_span32(ctx, n, zptr, span->array->z, span->array->mask);
       }
-      if (passed < span->end)
+#if 1
+      if (passed < span->end) {
          span->writeAll = GL_FALSE;
+      }
+#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 --;
+      }
+#endif
       return passed;
    }
 }
@@ -844,7 +827,7 @@ software_depth_test_pixels16( GLcontext *ctx, GLuint n,
         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");
@@ -1090,7 +1073,7 @@ software_depth_test_pixels32( GLcontext *ctx, GLuint n,
         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");
@@ -1324,7 +1307,7 @@ hardware_depth_test_pixels( GLcontext *ctx, GLuint n, GLdepth zbuffer[],
         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 hardware_depth_test_pixels");
@@ -1333,15 +1316,19 @@ hardware_depth_test_pixels( GLcontext *ctx, GLuint n, GLdepth zbuffer[],
 
 
 
-void
-_mesa_depth_test_pixels( GLcontext *ctx,
-                         GLuint n, const GLint x[], const GLint y[],
-                         const GLdepth z[], GLubyte mask[] )
+static GLuint
+depth_test_pixels( GLcontext *ctx, struct sw_span *span )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   const GLuint n = span->end;
+   const GLint *x = span->array->x;
+   const GLint *y = span->array->y;
+   const GLdepth *z = span->array->z;
+   GLubyte *mask = span->array->mask;
+
    if (swrast->Driver.ReadDepthPixels) {
       /* read depth values from hardware Z buffer */
-      GLdepth zbuffer[PB_SIZE];
+      GLdepth zbuffer[MAX_WIDTH];
       (*swrast->Driver.ReadDepthPixels)(ctx, n, x, y, zbuffer);
 
       hardware_depth_test_pixels( ctx, n, zbuffer, z, mask );
@@ -1357,9 +1344,119 @@ _mesa_depth_test_pixels( GLcontext *ctx,
       else
          software_depth_test_pixels32(ctx, n, x, y, z, mask);
    }
+   return n; /* 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, struct sw_span *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, struct sw_span *span )
+{
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   GLdepth zMin = (GLdepth) (ctx->Depth.BoundsMin * ctx->DepthMaxF + 0.5F);
+   GLdepth zMax = (GLdepth) (ctx->Depth.BoundsMax * ctx->DepthMaxF + 0.5F);
+   GLubyte *mask = span->array->mask;
+   GLuint i;
+   GLboolean anyPass = GL_FALSE;
+
+   if (swrast->Driver.ReadDepthPixels) {
+      /* read depth values from hardware Z buffer */
+      GLdepth zbuffer[MAX_WIDTH];
+      ASSERT(span->end <= MAX_WIDTH);
+      if (span->arrayMask & SPAN_XY)
+         (*swrast->Driver.ReadDepthPixels)(ctx, span->end, span->array->x,
+                                           span->array->y, zbuffer);
+      else
+         (*swrast->Driver.ReadDepthSpan)(ctx, span->end, span->x, span->y,
+                                         zbuffer);
+      for (i = 0; i < span->end; i++) {
+         if (mask[i]) {
+            if (zbuffer[i] < zMin || zbuffer[i] > zMax)
+               mask[i] = GL_FALSE;
+            else
+               anyPass = GL_TRUE;
+         }
+      }
+   }
+   else {
+      /* software Z buffer */
+      if (span->arrayMask & SPAN_XY) {
+         if (ctx->Visual.depthBits <= 16) {
+            /* 16 bits / Z */
+            for (i = 0; i < span->end; i++) {
+               if (mask[i]) {
+                  const GLushort *zPtr = Z_ADDRESS16(ctx, span->array->x[i],
+                                                     span->array->y[i]);
+                  if (*zPtr < zMin || *zPtr > zMax)
+                     mask[i] = GL_FALSE;
+                  else
+                     anyPass = GL_TRUE;
+               }
+            }
+         }
+         else {
+            /* 32 bits / Z */
+            for (i = 0; i < span->end; i++) {
+               if (mask[i]) {
+                  const GLuint *zPtr = Z_ADDRESS32(ctx, span->array->x[i],
+                                                   span->array->y[i]);
+                  if (*zPtr < zMin || *zPtr > zMax)
+                     mask[i] = GL_FALSE;
+                  else
+                     anyPass = GL_TRUE;
+               }
+            }
+         }
+      }
+      else {
+         if (ctx->Visual.depthBits <= 16) {
+            /* 16 bits / Z */
+            const GLushort *zPtr = Z_ADDRESS16(ctx, span->x, span->y);
+            for (i = 0; i < span->end; i++) {
+               if (mask[i]) {
+                  if (zPtr[i] < zMin || zPtr[i] > zMax)
+                     mask[i] = GL_FALSE;
+                  else
+                     anyPass = GL_TRUE;
+               }
+            }
+         }
+         else {
+            /* 32 bits / Z */
+            const GLuint *zPtr = Z_ADDRESS32(ctx, span->x, span->y);
+            for (i = 0; i < span->end; i++) {
+               if (mask[i]) {
+                  if (zPtr[i] < zMin || zPtr[i] > zMax)
+                     mask[i] = GL_FALSE;
+                  else
+                     anyPass = GL_TRUE;
+               }
+            }
+         }
+      }
+   }
+   return anyPass;
+}
 
 
 
@@ -1368,18 +1465,18 @@ _mesa_depth_test_pixels( GLcontext *ctx,
 /**********************************************************************/
 
 
-/*
+/**
  * Read a span of depth values from the depth buffer.
  * This function does clipping before calling the device driver function.
  */
 void
-_mesa_read_depth_span( GLcontext *ctx,
+_swrast_read_depth_span( GLcontext *ctx,
                        GLint n, GLint x, GLint y, GLdepth depth[] )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
 
-   if (y < 0 || y >= ctx->DrawBuffer->Height ||
-       x + (GLint) n <= 0 || x >= ctx->DrawBuffer->Width) {
+   if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height ||
+       x + (GLint) n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) {
       /* span is completely outside framebuffer */
       GLint i;
       for (i = 0; i < n; i++)
@@ -1396,8 +1493,8 @@ _mesa_read_depth_span( GLcontext *ctx,
       n -= dx;
       depth += dx;
    }
-   if (x + n > ctx->DrawBuffer->Width) {
-      GLint dx = x + n - ctx->DrawBuffer->Width;
+   if (x + n > (GLint) ctx->DrawBuffer->Width) {
+      GLint dx = x + n - (GLint) ctx->DrawBuffer->Width;
       GLint i;
       for (i = 0; i < dx; i++)
          depth[n - i - 1] = 0;
@@ -1430,7 +1527,7 @@ _mesa_read_depth_span( GLcontext *ctx,
    }
    else {
       /* no depth buffer */
-      BZERO(depth, n * sizeof(GLfloat));
+      _mesa_bzero(depth, n * sizeof(GLfloat));
    }
 
 }
@@ -1438,7 +1535,7 @@ _mesa_read_depth_span( GLcontext *ctx,
 
 
 
-/*
+/**
  * 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
@@ -1446,14 +1543,14 @@ _mesa_read_depth_span( GLcontext *ctx,
  * Output:  depth - the array of depth values
  */
 void
-_mesa_read_depth_span_float( GLcontext *ctx,
+_swrast_read_depth_span_float( GLcontext *ctx,
                              GLint n, GLint x, GLint y, GLfloat depth[] )
 {
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
    const GLfloat scale = 1.0F / ctx->DepthMaxF;
 
-   if (y < 0 || y >= ctx->DrawBuffer->Height ||
-       x + (GLint) n <= 0 || x >= ctx->DrawBuffer->Width) {
+   if (y < 0 || y >= (GLint) ctx->DrawBuffer->Height ||
+       x + (GLint) n <= 0 || x >= (GLint) ctx->DrawBuffer->Width) {
       /* span is completely outside framebuffer */
       GLint i;
       for (i = 0; i < n; i++)
@@ -1469,8 +1566,8 @@ _mesa_read_depth_span_float( GLcontext *ctx,
       n -= dx;
       x = 0;
    }
-   if (x + n > ctx->DrawBuffer->Width) {
-      GLint dx = x + n - ctx->DrawBuffer->Width;
+   if (x + n > (GLint) ctx->DrawBuffer->Width) {
+      GLint dx = x + n - (GLint) ctx->DrawBuffer->Width;
       GLint i;
       for (i = 0; i < dx; i++)
          depth[n - i - 1] = 0.0F;
@@ -1509,7 +1606,7 @@ _mesa_read_depth_span_float( GLcontext *ctx,
    }
    else {
       /* no depth buffer */
-      BZERO(depth, n * sizeof(GLfloat));
+      _mesa_bzero(depth, n * sizeof(GLfloat));
    }
 }
 
@@ -1521,60 +1618,80 @@ _mesa_read_depth_span_float( GLcontext *ctx,
 
 
 
-/*
+/**
  * 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.
  */
 void
-_mesa_alloc_depth_buffer( GLcontext *ctx )
+_swrast_alloc_depth_buffer( GLframebuffer *buffer )
 {
-   /* deallocate current depth buffer if present */
-   if (ctx->DrawBuffer->UseSoftwareDepthBuffer) {
-      GLint bytesPerValue;
+   GLint bytesPerValue;
 
-      if (ctx->DrawBuffer->DepthBuffer) {
-         FREE(ctx->DrawBuffer->DepthBuffer);
-         ctx->DrawBuffer->DepthBuffer = NULL;
-      }
+   ASSERT(buffer->UseSoftwareDepthBuffer);
 
-      /* allocate new depth buffer, but don't initialize it */
-      if (ctx->Visual.depthBits <= 16)
-         bytesPerValue = sizeof(GLushort);
-      else
-         bytesPerValue = sizeof(GLuint);
+   /* 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);
 
-      ctx->DrawBuffer->DepthBuffer = MALLOC( ctx->DrawBuffer->Width
-                                             * ctx->DrawBuffer->Height
-                                             * bytesPerValue );
+   buffer->DepthBuffer = MESA_PBUFFER_ALLOC(buffer->Width * buffer->Height
+                                            * bytesPerValue);
 
-      if (!ctx->DrawBuffer->DepthBuffer) {
-         /* out of memory */
+   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" );
+         _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 )
+_swrast_clear_depth_buffer( GLcontext *ctx )
 {
+   SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
    if (ctx->Visual.depthBits == 0
-       || !ctx->DrawBuffer->DepthBuffer
        || !ctx->Depth.Mask) {
       /* no depth buffer, or writing to it is disabled */
       return;
    }
 
+   if (swrast->Driver.WriteMonoDepthSpan) {
+      const GLdepth clearValue = (GLdepth)(ctx->Depth.Clear * ctx->DepthMax);
+      const GLint x = ctx->DrawBuffer->_Xmin;
+      const GLint y = ctx->DrawBuffer->_Ymin;
+      const GLint height = ctx->DrawBuffer->_Ymax - ctx->DrawBuffer->_Ymin;
+      const GLint width  = ctx->DrawBuffer->_Xmax - ctx->DrawBuffer->_Xmin;
+      GLint i;
+
+      for (i = 0; i < height; i++) {
+         (*swrast->Driver.WriteMonoDepthSpan)( ctx, width, x, y + i,
+                                               clearValue, NULL );
+      }
+
+      return;
+   }
+
+   if (!ctx->DrawBuffer->DepthBuffer)
+      return;
+
    /* The loops in this function have been written so the IRIX 5.3
     * C compiler can unroll them.  Hopefully other compilers can too!
     */
@@ -1618,7 +1735,7 @@ _mesa_clear_depth_buffer( GLcontext *ctx )
          const GLushort clearValue = (GLushort) (ctx->Depth.Clear * ctx->DepthMax);
          if ((clearValue & 0xff) == (clearValue >> 8)) {
             if (clearValue == 0) {
-               BZERO(ctx->DrawBuffer->DepthBuffer,
+               _mesa_bzero(ctx->DrawBuffer->DepthBuffer,
                      2*ctx->DrawBuffer->Width*ctx->DrawBuffer->Height);
             }
             else {
@@ -1652,7 +1769,7 @@ _mesa_clear_depth_buffer( GLcontext *ctx )
          /* >16 bit depth buffer */
          const GLuint clearValue = (GLuint) (ctx->Depth.Clear * ctx->DepthMax);
          if (clearValue == 0) {
-            BZERO(ctx->DrawBuffer->DepthBuffer,
+            _mesa_bzero(ctx->DrawBuffer->DepthBuffer,
                 ctx->DrawBuffer->Width*ctx->DrawBuffer->Height*sizeof(GLuint));
          }
          else {