From 116133af3499947500a6d0c877fbc8f564ee4c76 Mon Sep 17 00:00:00 2001 From: Maxim Levitsky Date: Thu, 19 May 2011 12:50:28 +0200 Subject: 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 deletion(-) (limited to 'src/gallium/drivers') 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 -- cgit v1.2.3