summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxim Levitsky <maximlevitsky@gmail.com>2011-05-19 12:50:28 +0200
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>2011-05-19 12:50:28 +0200
commit116133af3499947500a6d0c877fbc8f564ee4c76 (patch)
tree2370ce4f522c990b15e89931cc0569313bbfef68
parentbfaa458445978b5210e6866256d19448db2c6dd0 (diff)
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.
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c3
-rw-r--r--src/gallium/drivers/nv50/nv50_shader_state.c8
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c3
-rw-r--r--src/gallium/drivers/nv50/nv50_tgsi_to_nc.c27
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 41d3e14dc0..4def93d6b8 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 82c346cb5e..5d3f52c38c 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 cdf1a982fc..11561f5a8e 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 25dcaaea14..15aa40cddd 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