i965: allow for nonconsecutive elements of gl_ClipDistance to be enabled.
authorPaul Berry <stereotype441@gmail.com>
Tue, 20 Sep 2011 23:43:06 +0000 (16:43 -0700)
committerPaul Berry <stereotype441@gmail.com>
Wed, 28 Sep 2011 18:38:03 +0000 (11:38 -0700)
When using user-defined clipping planes, the i965 driver compacts the
array of clipping planes so that disabled clipping planes do not
appear in it--this saves precious push constant space and makes it
easier to generate the pre-GEN6 clip program.  As a result, when
enabling clipping planes in GEN6+ hardware, we always enable clipping
planes 0 through n-1 (where n is the number of clipping planes
enabled), regardless of which clipping planes the user actually
requested.

However, we can't do this when using gl_ClipDistance, because it would
be prohibitively complex to compact the gl_ClipDistance array inside
the user-supplied vertex shader.  So, when enabling clipping planes in
GEN6+ hardware, if gl_ClipDistance is in use, we need to pass the
user-supplied enable flags directly through to the hardware rather
than just enabling the first n planes.

Fixes Piglit test vs-clip-distance-enables.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/mesa/drivers/dri/i965/brw_state.h
src/mesa/drivers/dri/i965/gen6_clip_state.c
src/mesa/drivers/dri/i965/gen7_clip_state.c

index 6fc95eb646e7e0a327f647af171c8b48169970b2..fabf0c0d26af579b8350f922a0cf0c2b817d91b9 100644 (file)
@@ -213,4 +213,9 @@ get_attr_override(struct brw_vue_map *vue_map, int urb_entry_read_offset,
 unsigned int
 gen7_depth_format(struct brw_context *brw);
 
+/* gen6_clip_state.c */
+uint32_t
+brw_compute_userclip_flags(bool uses_clip_distance,
+                           GLbitfield clip_planes_enabled);
+
 #endif
index 872465dacc2ccfcaca9e8cd216d8e703a0602ddd..ffe2c53acfd630849c57150d4b594445072a69a1 100644 (file)
 #include "brw_util.h"
 #include "intel_batchbuffer.h"
 
+uint32_t
+brw_compute_userclip_flags(bool uses_clip_distance,
+                           GLbitfield clip_planes_enabled)
+{
+   if (uses_clip_distance) {
+      /* When using gl_ClipDistance, it is up to the shader to decide which
+       * clip distance values to use.
+       */
+      return clip_planes_enabled;
+   } else {
+      /* When using clipping planes, we compact the ones that are in use so
+       * that they are always numbered consecutively from zero, so we need to
+       * enable clipping planes 0 through n-1 in the hardware regardless of
+       * which planes the user has selected.
+       */
+      return (1 << brw_count_bits(clip_planes_enabled)) - 1;
+   }
+}
+
 static void
 upload_clip_state(struct brw_context *brw)
 {
@@ -39,6 +58,10 @@ upload_clip_state(struct brw_context *brw)
    uint32_t depth_clamp = 0;
    uint32_t provoking, userclip;
 
+   /* BRW_NEW_VERTEX_PROGRAM */
+   struct brw_vertex_program *vp =
+      (struct brw_vertex_program *)brw->vertex_program;
+
    if (!ctx->Transform.DepthClamp)
       depth_clamp = GEN6_CLIP_Z_TEST;
 
@@ -56,7 +79,8 @@ upload_clip_state(struct brw_context *brw)
    }
 
    /* _NEW_TRANSFORM */
-   userclip = (1 << brw_count_bits(ctx->Transform.ClipPlanesEnabled)) - 1;
+   userclip = brw_compute_userclip_flags(vp->program.UsesClipDistance,
+                                         ctx->Transform.ClipPlanesEnabled);
 
    BEGIN_BATCH(4);
    OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2));
@@ -77,7 +101,7 @@ upload_clip_state(struct brw_context *brw)
 const struct brw_tracked_state gen6_clip_state = {
    .dirty = {
       .mesa  = _NEW_TRANSFORM | _NEW_LIGHT,
-      .brw   = BRW_NEW_CONTEXT,
+      .brw   = BRW_NEW_CONTEXT | BRW_NEW_VERTEX_PROGRAM,
       .cache = 0
    },
    .emit = upload_clip_state,
index c23ba8cab5ca2ca91066d47cfbd16807da735809..5458ce81046abbf28f168321ba5fcc2d1bfef3dd 100644 (file)
@@ -39,6 +39,10 @@ upload_clip_state(struct brw_context *brw)
    /* _NEW_BUFFERS */
    GLboolean render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0;
 
+   /* BRW_NEW_VERTEX_PROGRAM */
+   struct brw_vertex_program *vp =
+      (struct brw_vertex_program *)brw->vertex_program;
+
    dw1 |= GEN7_CLIP_EARLY_CULL;
 
    /* _NEW_POLYGON */
@@ -82,7 +86,8 @@ upload_clip_state(struct brw_context *brw)
    }
 
    /* _NEW_TRANSFORM */
-   userclip = (1 << brw_count_bits(ctx->Transform.ClipPlanesEnabled)) - 1;
+   userclip = brw_compute_userclip_flags(vp->program.UsesClipDistance,
+                                         ctx->Transform.ClipPlanesEnabled);
 
    BEGIN_BATCH(4);
    OUT_BATCH(_3DSTATE_CLIP << 16 | (4 - 2));
@@ -106,7 +111,7 @@ const struct brw_tracked_state gen7_clip_state = {
                 _NEW_POLYGON |
                 _NEW_LIGHT |
                 _NEW_TRANSFORM),
-      .brw   = BRW_NEW_CONTEXT,
+      .brw   = BRW_NEW_CONTEXT | BRW_NEW_VERTEX_PROGRAM,
       .cache = 0
    },
    .emit = upload_clip_state,