summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers
diff options
context:
space:
mode:
authorMaxim Levitsky <[email protected]>2011-05-19 12:50:28 +0200
committerChristoph Bumiller <[email protected]>2011-05-19 12:50:28 +0200
commit116133af3499947500a6d0c877fbc8f564ee4c76 (patch)
tree2370ce4f522c990b15e89931cc0569313bbfef68 /src/gallium/drivers
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.
Diffstat (limited to 'src/gallium/drivers')
-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 41d3e14dc0f..4def93d6b84 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 82c346cb5ea..5d3f52c38c1 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 cdf1a982fcc..11561f5a8e6 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 25dcaaea14f..15aa40cddd1 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