Mesa (master): nv50: add support for user clip planes

Christoph Bumiller chrisbmr at kemper.freedesktop.org
Thu May 19 11:21:00 UTC 2011


Module: Mesa
Branch: master
Commit: 116133af3499947500a6d0c877fbc8f564ee4c76
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=116133af3499947500a6d0c877fbc8f564ee4c76

Author: Maxim Levitsky <maximlevitsky at gmail.com>
Date:   Thu May 19 12:50:28 2011 +0200

nv50: add support for user clip planes

Clip distance is calculated each time vertex position is written
which is suboptiomal is some cases but very safe.
User clip planes are an obsolete feature anyway.

Every time number of clip planes increases, the vertex program
is recompiled.
That ensures no overhead in normal case (no user clip planes)
and reasonable overhead otherwise.

Fixes 3D windows in compiz, and reflection effect in neverball.
Also fixes compiz expo plugin when windows were dragged and each
window shown 3 times.

---

 src/gallium/drivers/nv50/nv50_program.c        |    3 ++
 src/gallium/drivers/nv50/nv50_shader_state.c   |    8 ++++++-
 src/gallium/drivers/nv50/nv50_state_validate.c |    3 ++
 src/gallium/drivers/nv50/nv50_tgsi_to_nc.c     |   27 ++++++++++++++++++++++++
 4 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 41d3e14..4def93d 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -395,6 +395,9 @@ nv50_vertprog_prepare(struct nv50_translation_info *ti)
       }
    }
 
+   p->vp.clpd = p->max_out;
+   p->max_out += p->vp.clpd_nr;
+
    for (i = 0; i < TGSI_SEMANTIC_COUNT; ++i) {
       switch (ti->sysval_map[i]) {
       case 2:
diff --git a/src/gallium/drivers/nv50/nv50_shader_state.c b/src/gallium/drivers/nv50/nv50_shader_state.c
index 82c346c..5d3f52c 100644
--- a/src/gallium/drivers/nv50/nv50_shader_state.c
+++ b/src/gallium/drivers/nv50/nv50_shader_state.c
@@ -170,6 +170,12 @@ nv50_vertprog_validate(struct nv50_context *nv50)
    struct nouveau_channel *chan = nv50->screen->base.channel;
    struct nv50_program *vp = nv50->vertprog;
 
+   if (nv50->clip.nr > vp->vp.clpd_nr) {
+      if (vp->translated)
+         nv50_program_destroy(nv50, vp);
+      vp->vp.clpd_nr = nv50->clip.nr;
+   }
+
    if (!nv50_program_validate(nv50, vp))
          return;
 
@@ -369,7 +375,7 @@ nv50_fp_linkage_validate(struct nv50_context *nv50)
    m = nv50_vec4_map(map, 0, lin, &dummy, &vp->out[0]);
 
    for (c = 0; c < vp->vp.clpd_nr; ++c)
-      map[m++] |= vp->vp.clpd + c;
+      map[m++] = vp->vp.clpd + c;
 
    colors |= m << 8; /* adjust BFC0 id */
 
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
index cdf1a98..11561f5 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -225,6 +225,9 @@ nv50_validate_clip(struct nv50_context *nv50)
 
    BEGIN_RING(chan, RING_3D(VP_CLIP_DISTANCE_ENABLE), 1);
    OUT_RING  (chan, (1 << nv50->clip.nr) - 1);
+
+   if (nv50->vertprog && nv50->clip.nr > nv50->vertprog->vp.clpd_nr)
+      nv50->dirty |= NV50_NEW_VERTPROG;
 }
 
 static void
diff --git a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
index 25dcaae..15aa40c 100644
--- a/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
+++ b/src/gallium/drivers/nv50/nv50_tgsi_to_nc.c
@@ -1552,6 +1552,8 @@ static void
 bld_instruction(struct bld_context *bld,
                 const struct tgsi_full_instruction *insn)
 {
+   struct nv50_program *prog = bld->ti->p;
+   const struct tgsi_full_dst_register *dreg = &insn->Dst[0];
    struct nv_value *src0;
    struct nv_value *src1;
    struct nv_value *src2;
@@ -1990,6 +1992,31 @@ bld_instruction(struct bld_context *bld,
 
    FOR_EACH_DST0_ENABLED_CHANNEL(c, insn)
       emit_store(bld, insn, c, dst0[c]);
+
+   if (prog->type == PIPE_SHADER_VERTEX && prog->vp.clpd_nr &&
+       dreg->Register.File == TGSI_FILE_OUTPUT && !dreg->Register.Indirect &&
+       prog->out[dreg->Register.Index].sn == TGSI_SEMANTIC_POSITION) {
+
+      int p;
+      for (p = 0; p < prog->vp.clpd_nr; p++) {
+         struct nv_value *clipd = NULL;
+
+         for (c = 0; c < 4; c++) {
+            temp = new_value(bld->pc, NV_FILE_MEM_C(15), NV_TYPE_F32);
+            temp->reg.id = p * 4 + c;
+            temp = bld_insn_1(bld, NV_OP_LDA, temp);
+
+            clipd = clipd ?
+                        bld_insn_3(bld, NV_OP_MAD, dst0[c], temp, clipd) :
+                        bld_insn_2(bld, NV_OP_MUL, dst0[c], temp);
+         }
+
+         temp = bld_insn_1(bld, NV_OP_MOV, clipd);
+         temp->reg.file = NV_FILE_OUT;
+         temp->reg.id = bld->ti->p->vp.clpd + p;
+         temp->insn->fixed = 1;
+      }
+   }
 }
 
 static INLINE void




More information about the mesa-commit mailing list