nv50: add support for user clip planes
authorMaxim Levitsky <maximlevitsky@gmail.com>
Thu, 19 May 2011 10:50:28 +0000 (12:50 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 19 May 2011 10:50:28 +0000 (12:50 +0200)
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
src/gallium/drivers/nv50/nv50_shader_state.c
src/gallium/drivers/nv50/nv50_state_validate.c
src/gallium/drivers/nv50/nv50_tgsi_to_nc.c

index 41d3e14dc0f4134d142a5a0428e87bbeca5fa068..4def93d6b846f8a8997ad3496318155ebe11fd57 100644 (file)
@@ -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:
index 82c346cb5eab340e86ad9d3bc70354fd2e8e1086..5d3f52c38c1b3f00a240f1db7a554554131acb06 100644 (file)
@@ -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 */
 
index cdf1a982fcc32df3a0079bd1c0c5b42eba2c9920..11561f5a8e67938173aa4b3a30b47cbc89dc3e2e 100644 (file)
@@ -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
index 25dcaaea14f6e1362397aac15aedba17285b6dbe..15aa40cddd10ecb8dacac450b64a6f4ce783ef1e 100644 (file)
@@ -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