Implemented GL_EXT_depth_bounds_test.
authorBrian Paul <brian.paul@tungstengraphics.com>
Mon, 21 Apr 2003 15:02:17 +0000 (15:02 +0000)
committerBrian Paul <brian.paul@tungstengraphics.com>
Mon, 21 Apr 2003 15:02:17 +0000 (15:02 +0000)
src/mesa/main/depth.c
src/mesa/main/depth.h
src/mesa/main/dlist.c
src/mesa/main/enable.c
src/mesa/main/extensions.c
src/mesa/main/get.c
src/mesa/main/mtypes.h
src/mesa/main/state.c
src/mesa/swrast/s_depth.c
src/mesa/swrast/s_depth.h
src/mesa/swrast/s_span.c

index 8383bcc..9d95500 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: depth.c,v 1.31 2002/10/24 23:57:20 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"),
@@ -116,3 +114,29 @@ _mesa_DepthMask( GLboolean flag )
    if (ctx->Driver.DepthMask)
       ctx->Driver.DepthMask( ctx, flag );
 }
+
+
+
+/* GL_EXT_depth_bounds_test */
+void
+_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   ASSERT_OUTSIDE_BEGIN_END(ctx);
+
+   if (zmin > zmax) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "glDepthBoundsEXT(zmin > zmax)");
+      return;
+   }
+
+   zmin = CLAMP(zmin, 0.0, 1.0);
+   zmax = CLAMP(zmax, 0.0, 1.0);
+
+   if (ctx->Depth.BoundsMin == zmin && ctx->Depth.BoundsMax == zmax)
+      return;
+
+   FLUSH_VERTICES(ctx, _NEW_DEPTH);
+   ctx->Depth.BoundsMin = zmin;
+   ctx->Depth.BoundsMax = zmax;
+}
+
index e9c2885..b90d723 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: depth.h,v 1.11 2001/03/12 00:48:37 gareth Exp $ */
-
 /*
  * Mesa 3-D graphics library
- * Version:  3.5
+ * Version:  5.1
  *
- * Copyright (C) 1999-2001  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"),
@@ -48,6 +46,8 @@ extern void
 _mesa_DepthMask( GLboolean flag );
 
 
+extern void
+_mesa_DepthBoundsEXT( GLclampd zmin, GLclampd zmax );
 
 
 #endif
index d47437f..4399385 100644 (file)
@@ -255,6 +255,8 @@ typedef enum {
         OPCODE_PROGRAM_NAMED_PARAMETER_NV,
         /* GL_EXT_stencil_two_side */
         OPCODE_ACTIVE_STENCIL_FACE_EXT,
+        /* GL_EXT_depth_bounds_test */
+        OPCODE_DEPTH_BOUNDS_EXT,
        /* The following three are meta instructions */
        OPCODE_ERROR,           /* raise compiled-in error */
        OPCODE_CONTINUE,
@@ -671,6 +673,8 @@ void _mesa_init_lists( void )
       InstSize[OPCODE_PROGRAM_NAMED_PARAMETER_NV] = 8;
       /* GL_EXT_stencil_two_side */
       InstSize[OPCODE_ACTIVE_STENCIL_FACE_EXT] = 2;
+      /* GL_EXT_depth_bounds_test */
+      InstSize[OPCODE_DEPTH_BOUNDS_EXT] = 3;
    }
    init_flag = 1;
 }
@@ -4366,6 +4370,24 @@ static void save_ActiveStencilFaceEXT( GLenum face )
 }
 
 
+/* GL_EXT_depth_bounds_test */
+static void save_DepthBoundsEXT( GLclampd zmin, GLclampd zmax )
+{
+   GET_CURRENT_CONTEXT(ctx);
+   Node *n;
+   ASSERT_OUTSIDE_SAVE_BEGIN_END_AND_FLUSH(ctx);
+   n = ALLOC_INSTRUCTION( ctx, OPCODE_ACTIVE_STENCIL_FACE_EXT, 2 );
+   if (n) {
+      n[1].f = zmin;
+      n[2].f = zmax;
+   }
+   if (ctx->ExecuteFlag) {
+      (*ctx->Exec->DepthBoundsEXT)( zmin, zmax );
+   }
+}
+
+
+
 
 /* KW: Compile commands
  *
@@ -5107,6 +5129,13 @@ execute_list( GLcontext *ctx, GLuint list )
             break;
 #endif
 
+         case OPCODE_ACTIVE_STENCIL_FACE_EXT:
+            (*ctx->Exec->ActiveStencilFaceEXT)(n[1].e);
+            break;
+         case OPCODE_DEPTH_BOUNDS_EXT:
+            (*ctx->Exec->DepthBoundsEXT)(n[1].f, n[2].f);
+            break;
+
         case OPCODE_CONTINUE:
            n = (Node *) n[1].next;
            break;
@@ -6493,6 +6522,9 @@ _mesa_init_dlist_table( struct _glapi_table *table, GLuint tableSize )
    /* 268. GL_EXT_stencil_two_side */
    table->ActiveStencilFaceEXT = save_ActiveStencilFaceEXT;
 
+   /* ???. GL_EXT_depth_bounds_test */
+   table->DepthBoundsEXT = save_DepthBoundsEXT;
+
    /* ARB 1. GL_ARB_multitexture */
    table->ActiveTextureARB = save_ActiveTextureARB;
    table->ClientActiveTextureARB = exec_ClientActiveTextureARB;
index 5fe6549..747c3f6 100644 (file)
@@ -923,6 +923,20 @@ void _mesa_set_enable( GLcontext *ctx, GLenum cap, GLboolean state )
          break;
 #endif /* FEATURE_ARB_fragment_program */
 
+      /* GL_EXT_depth_bounds_test */
+      case GL_DEPTH_BOUNDS_TEST_EXT:
+         CHECK_EXTENSION(EXT_depth_bounds_test, cap);
+         if (state && ctx->Visual.depthBits==0) {
+            _mesa_warning(ctx,
+                   "glEnable(GL_DEPTH_BOUNDS_TEST_EXT) but no depth buffer");
+            return;
+         }
+         if (ctx->Depth.BoundsTest == state)
+            return;
+         FLUSH_VERTICES(ctx, _NEW_DEPTH);
+         ctx->Depth.BoundsTest = state;
+         break;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM,
                      "%s(0x%x)", state ? "glEnable" : "glDisable", cap);
@@ -1319,6 +1333,11 @@ _mesa_IsEnabled( GLenum cap )
          return ctx->FragmentProgram.Enabled;
 #endif /* FEATURE_ARB_fragment_program */
 
+      /* GL_EXT_depth_bounds_test */
+      case GL_DEPTH_BOUNDS_TEST_EXT:
+         CHECK_EXTENSION(EXT_depth_bounds_test);
+         return ctx->Depth.BoundsTest;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glIsEnabled(0x%x)", (int) cap);
         return GL_FALSE;
index 59ec4c2..2f5bc75 100644 (file)
@@ -81,6 +81,7 @@ static struct {
    { ON,  "GL_EXT_clip_volume_hint",           F(EXT_clip_volume_hint) },
    { OFF, "GL_EXT_convolution",                F(EXT_convolution) },
    { ON,  "GL_EXT_compiled_vertex_array",      F(EXT_compiled_vertex_array) },
+   { OFF, "GL_EXT_depth_bounds_test",          F(EXT_depth_bounds_test) },
    { OFF, "GL_EXT_fog_coord",                  F(EXT_fog_coord) },
    { OFF, "GL_EXT_histogram",                  F(EXT_histogram) },
    { OFF, "GL_EXT_multi_draw_arrays",          F(EXT_multi_draw_arrays) },
@@ -148,6 +149,9 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
 {
    const char *extensions[] = {
       "GL_ARB_depth_texture",
+#if FEATURE_ARB_fragment_program
+      "GL_ARB_fragment_program",
+#endif
       "GL_ARB_imaging",
       "GL_ARB_multitexture",
       "GL_ARB_point_parameters",
@@ -160,6 +164,9 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
       "GL_ARB_texture_env_crossbar",
       "GL_ARB_texture_env_dot3",
       "GL_ARB_texture_mirrored_repeat",
+#if FEATURE_ARB_vertex_program
+      "GL_ARB_vertex_program",
+#endif
       "GL_ATI_texture_env_combine3",
       "GL_ATI_texture_mirror_once",
       "GL_EXT_blend_color",
@@ -168,6 +175,7 @@ _mesa_enable_sw_extensions(GLcontext *ctx)
       "GL_EXT_blend_minmax",
       "GL_EXT_blend_subtract",
       "GL_EXT_convolution",
+      "GL_EXT_depth_bounds_test",
       "GL_EXT_fog_coord",
       "GL_EXT_histogram",
       "GL_EXT_paletted_texture",
index 65c4106..dd1c001 100644 (file)
@@ -1593,6 +1593,17 @@ _mesa_GetBooleanv( GLenum pname, GLboolean *params )
        */
 #endif
 
+      /* GL_EXT_depth_bounds_test */
+      case GL_DEPTH_BOUNDS_TEST_EXT:
+         CHECK_EXTENSION_B(EXT_depth_bounds_test, pname);
+         params[0] = ctx->Depth.BoundsTest;
+         break;
+      case GL_DEPTH_BOUNDS_EXT:
+         CHECK_EXTENSION_B(EXT_depth_bounds_test, pname);
+         params[0] = FLOAT_TO_BOOL(ctx->Depth.BoundsMin);
+         params[1] = FLOAT_TO_BOOL(ctx->Depth.BoundsMax);
+         break;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetBooleanv(pname=0x%x)", pname);
    }
@@ -3079,6 +3090,17 @@ _mesa_GetDoublev( GLenum pname, GLdouble *params )
        */
 #endif
 
+      /* GL_EXT_depth_bounds_test */
+      case GL_DEPTH_BOUNDS_TEST_EXT:
+         CHECK_EXTENSION_D(EXT_depth_bounds_test, pname);
+         params[0] = (GLdouble) ctx->Depth.BoundsTest;
+         break;
+      case GL_DEPTH_BOUNDS_EXT:
+         CHECK_EXTENSION_D(EXT_depth_bounds_test, pname);
+         params[0] = ctx->Depth.BoundsMin;
+         params[1] = ctx->Depth.BoundsMax;
+         break;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetDoublev(pname=0x%x)", pname);
    }
@@ -4541,6 +4563,17 @@ _mesa_GetFloatv( GLenum pname, GLfloat *params )
        */
 #endif
 
+      /* GL_EXT_depth_bounds_test */
+      case GL_DEPTH_BOUNDS_TEST_EXT:
+         CHECK_EXTENSION_F(EXT_depth_bounds_test, pname);
+         params[0] = (GLfloat) ctx->Depth.BoundsTest;
+         break;
+      case GL_DEPTH_BOUNDS_EXT:
+         CHECK_EXTENSION_F(EXT_depth_bounds_test, pname);
+         params[0] = ctx->Depth.BoundsMin;
+         params[1] = ctx->Depth.BoundsMax;
+         break;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetFloatv(0x%x)", pname);
    }
@@ -6041,6 +6074,17 @@ _mesa_GetIntegerv( GLenum pname, GLint *params )
        */
 #endif
 
+      /* GL_EXT_depth_bounds_test */
+      case GL_DEPTH_BOUNDS_TEST_EXT:
+         CHECK_EXTENSION_I(EXT_depth_bounds_test, pname);
+         params[0] = ctx->Depth.BoundsTest;
+         break;
+      case GL_DEPTH_BOUNDS_EXT:
+         CHECK_EXTENSION_I(EXT_depth_bounds_test, pname);
+         params[0] = (GLint) ctx->Depth.BoundsMin;
+         params[1] = (GLint) ctx->Depth.BoundsMax;
+         break;
+
       default:
          _mesa_error(ctx, GL_INVALID_ENUM, "glGetIntegerv(pname=0x%x)", pname);
    }
index edea218..b906ef4 100644 (file)
@@ -397,6 +397,8 @@ struct gl_depthbuffer_attrib {
    GLboolean Test;             /* Depth buffering enabled flag */
    GLboolean Mask;             /* Depth buffer writable? */
    GLboolean OcclusionTest;    /* GL_HP_occlusion_test */
+   GLboolean BoundsTest;        /* GL_EXT_depth_bounds_test */
+   GLfloat BoundsMin, BoundsMax;/* GL_EXT_depth_bounds_test */
 };
 
 
@@ -1466,6 +1468,7 @@ struct gl_extensions {
    GLboolean EXT_clip_volume_hint;
    GLboolean EXT_convolution;
    GLboolean EXT_compiled_vertex_array;
+   GLboolean EXT_depth_bounds_test;
    GLboolean EXT_fog_coord;
    GLboolean EXT_histogram;
    GLboolean EXT_multi_draw_arrays;
index 9608662..f14c3f9 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id: state.c,v 1.105 2003/04/21 14:55:17 brianp Exp $ */
-
 /*
  * Mesa 3-D graphics library
  * Version:  5.1
@@ -536,10 +534,8 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize)
    /* 268. GL_EXT_stencil_two_side */
    exec->ActiveStencilFaceEXT = _mesa_ActiveStencilFaceEXT;
 
-#if 0
    /* ???. GL_EXT_depth_bounds_test */
    exec->DepthBoundsEXT = _mesa_DepthBoundsEXT;
-#endif
 
    /* ARB 1. GL_ARB_multitexture */
    exec->ActiveTextureARB = _mesa_ActiveTextureARB;
index 1095857..fc242be 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: s_depth.c,v 1.26 2003/03/25 02:23:45 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"),
@@ -1364,6 +1362,103 @@ _swrast_depth_test_span( GLcontext *ctx, struct sw_span *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;
+}
+
+
 
 /**********************************************************************/
 /*****                      Read Depth Buffer                     *****/
index 9cc8e94..b972a84 100644 (file)
@@ -1,10 +1,8 @@
-/* $Id: s_depth.h,v 1.8 2003/03/25 02:23:45 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"),
@@ -37,11 +35,13 @@ extern GLvoid *
 _swrast_zbuffer_address(GLcontext *ctx, GLint x, GLint y);
 
 
-
 extern GLuint
 _swrast_depth_test_span( GLcontext *ctx, struct sw_span *span);
 
 
+extern GLboolean
+_swrast_depth_bounds_test( GLcontext *ctx, struct sw_span *span );
+
 
 extern void
 _swrast_read_depth_span( GLcontext *ctx,
index 231e549..cce69b8 100644 (file)
@@ -792,6 +792,13 @@ _swrast_write_index_span( GLcontext *ctx, struct sw_span *span)
       }
    }
 
+   /* Depth bounds test */
+   if (ctx->Depth.BoundsTest && ctx->Visual.depthBits > 0) {
+      if (!_swrast_depth_bounds_test(ctx, span)) {
+         return;
+      }
+   }
+
 #ifdef DEBUG
    if (span->arrayMask & SPAN_XY) {
       GLuint i;
@@ -962,6 +969,13 @@ _swrast_write_rgba_span( GLcontext *ctx, struct sw_span *span)
       }
    }
 
+   /* Depth bounds test */
+   if (ctx->Depth.BoundsTest && ctx->Visual.depthBits > 0) {
+      if (!_swrast_depth_bounds_test(ctx, span)) {
+         return;
+      }
+   }
+
 #ifdef DEBUG
    if (span->arrayMask & SPAN_XY) {
       GLuint i;
@@ -1168,6 +1182,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
 {
    const GLuint colorMask = *((GLuint *) ctx->Color.ColorMask);
    SWcontext *swrast = SWRAST_CONTEXT(ctx);
+   const GLuint origInterpMask = span->interpMask;
    const GLuint origArrayMask = span->arrayMask;
 
    ASSERT(span->primitive == GL_POINT  ||  span->primitive == GL_LINE ||
@@ -1253,6 +1268,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
 
       if (ctx->Stencil.Enabled) {
          if (!_swrast_stencil_and_ztest_span(ctx, span)) {
+            span->interpMask = origInterpMask;
             span->arrayMask = origArrayMask;
             return;
          }
@@ -1262,6 +1278,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
          ASSERT(span->arrayMask & SPAN_Z);
          /* regular depth testing */
          if (!_swrast_depth_test_span(ctx, span)) {
+            span->interpMask = origInterpMask;
             span->arrayMask = origArrayMask;
             return;
          }
@@ -1275,6 +1292,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
     * the occlusion test.
     */
    if (colorMask == 0x0) {
+      span->interpMask = origInterpMask;
       span->arrayMask = origArrayMask;
       return;
    }
@@ -1336,11 +1354,12 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
          _swrast_blend_span(ctx, span, span->array->rgba);
       }
 
+      /* Color component masking */
       if (colorMask != 0xffffffff) {
          _swrast_mask_rgba_span(ctx, span, span->array->rgba);
       }
 
+      /* write pixels */
       if (span->arrayMask & SPAN_XY) {
          /* array of pixel coords */
          (*swrast->Driver.WriteRGBAPixels)(ctx, span->end, span->array->x,
@@ -1365,6 +1384,7 @@ _swrast_write_texture_span( GLcontext *ctx, struct sw_span *span)
       }
    }
 
+   span->interpMask = origInterpMask;
    span->arrayMask = origArrayMask;
 }