draw: enable user plane clipping when clipdistance is used
authorZack Rusin <zackr@vmware.com>
Thu, 6 Jun 2013 03:17:10 +0000 (23:17 -0400)
committerZack Rusin <zackr@vmware.com>
Tue, 11 Jun 2013 02:04:27 +0000 (22:04 -0400)
Draw depended on clip_plane_enable being set in the rasterizer
to use clipdistance registers for clipping. That's really
unfriendly because it requires that rasterizer state to have
variants for every shader out there. Instead of depending on
the rasterizer lets extract the info from the available state:
if a shader writes clipdistance then we need to use it and we
need to clip using a number of planes equal to the number
of writen clipdistance components. This way clipdistances
just work.

Signed-off-by: Zack Rusin <zackr@vmware.com>
Reviewed-by: Jose Fonseca <jfonseca@vmware.com>
Reviewed-by: Brian Paul <brianp@vmware.com>
Reviewed-by: Roland Scheidegger <sroland@vmware.com>
src/gallium/auxiliary/draw/draw_cliptest_tmp.h
src/gallium/auxiliary/draw/draw_llvm.c

index 7a385c8d0672ca708688f5f7106c023320d15aaa..e4500dbd971d7137692e1b6ebd0d9262899a0de4 100644 (file)
@@ -35,8 +35,8 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
    const unsigned cv = draw_current_shader_clipvertex_output(pvs->draw);
    unsigned cd[2];
    const unsigned ef = pvs->draw->vs.edgeflag_output;
-   const unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
-   const unsigned flags = (FLAGS);
+   unsigned ucp_enable = pvs->draw->rasterizer->clip_plane_enable;
+   unsigned flags = (FLAGS);
    unsigned need_pipeline = 0;
    unsigned j;
    unsigned i;
@@ -46,12 +46,21 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
    int viewport_index = 
       draw_current_shader_uses_viewport_index(pvs->draw) ?
       *((unsigned*)out->data[viewport_index_output]): 0;
-      
+   int num_written_clipdistance =
+      draw_current_shader_num_written_clipdistances(pvs->draw);
+
    cd[0] = draw_current_shader_clipdistance_output(pvs->draw, 0);
    cd[1] = draw_current_shader_clipdistance_output(pvs->draw, 1);
-  
+
    if (cd[0] != pos || cd[1] != pos)
-     have_cd = true;
+      have_cd = true;
+
+   /* If clipdistance semantic has been written by the shader
+    * that means we're expected to do 'user plane clipping' */
+   if (num_written_clipdistance && !(flags & DO_CLIP_USER)) {
+      flags |= DO_CLIP_USER;
+      ucp_enable = (1 << num_written_clipdistance) - 1;
+   }
 
    for (j = 0; j < info->count; j++) {
       float *position = out->data[pos];
@@ -111,8 +120,7 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs,
 
          if (flags & DO_CLIP_USER) {
             unsigned ucp_mask = ucp_enable;
-            int num_written_clipdistance =
-               draw_current_shader_num_written_clipdistances(pvs->draw);
+
             while (ucp_mask) {
                unsigned plane_idx = ffs(ucp_mask)-1;
                ucp_mask &= ~(1 << plane_idx);
index 4a71955f56abf5518ab668b55a25c3d0a2d0004f..6733e08fa4aaa952552d61520e3015a476f8242d 100644 (file)
@@ -1146,6 +1146,11 @@ generate_clipmask(struct draw_llvm *llvm,
    if (cd[0] != pos || cd[1] != pos)
       have_cd = true;
 
+   if (num_written_clipdistance && !clip_user) {
+      clip_user = true;
+      ucp_enable = (1 << num_written_clipdistance) - 1;
+   }
+
    mask = lp_build_const_int_vec(gallivm, i32_type, 0);
    temp = lp_build_const_int_vec(gallivm, i32_type, 0);
    zero = lp_build_const_vec(gallivm, f32_type, 0);         /* 0.0f 0.0f 0.0f 0.0f */