summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nvfx/nvfx_state_emit.c
diff options
context:
space:
mode:
authorLuca Barbieri <luca@luca-barbieri.com>2010-08-23 00:31:08 +0200
committerLuca Barbieri <luca@luca-barbieri.com>2010-08-23 15:09:22 +0200
commitbfaa2577c6474222c79341c0d90685ed579f3414 (patch)
tree312af7416223bf2587c17e02806c9ae64a7a533c /src/gallium/drivers/nvfx/nvfx_state_emit.c
parenteb430b0e948caf02b9f4095d0e1435880073c2aa (diff)
nvfx: support clip planes sensibly and fix them on nv30
Before, we were discarding the compiled vertex program on each vertex program change. Now we compile the program as if there were 6 clip planes and dynamically patch in an "end program" bit at the right place. Also, nv30 should now work.
Diffstat (limited to 'src/gallium/drivers/nvfx/nvfx_state_emit.c')
-rw-r--r--src/gallium/drivers/nvfx/nvfx_state_emit.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/gallium/drivers/nvfx/nvfx_state_emit.c b/src/gallium/drivers/nvfx/nvfx_state_emit.c
index bd89a385d7..c43a75aaa2 100644
--- a/src/gallium/drivers/nvfx/nvfx_state_emit.c
+++ b/src/gallium/drivers/nvfx/nvfx_state_emit.c
@@ -90,6 +90,74 @@ nvfx_state_validate_common(struct nvfx_context *nvfx)
if(dirty & NVFX_NEW_STIPPLE)
nvfx_state_stipple_validate(nvfx);
+ if(nvfx->dirty & NVFX_NEW_UCP)
+ {
+ unsigned enables[7] =
+ {
+ 0,
+ NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0,
+ NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1,
+ NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2,
+ NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3,
+ NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4,
+ NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE0 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE1 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE2 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE3 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE4 | NV34TCL_VP_CLIP_PLANES_ENABLE_PLANE5,
+ };
+
+ if(!nvfx->use_vp_clipping)
+ {
+ WAIT_RING(chan, 2);
+ OUT_RING(chan, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE, 1));
+ OUT_RING(chan, 0);
+
+ WAIT_RING(chan, 6 * 4 + 1);
+ OUT_RING(chan, RING_3D(NV34TCL_VP_CLIP_PLANE_A(0), nvfx->clip.nr * 4));
+ OUT_RINGp(chan, &nvfx->clip.ucp[0][0], nvfx->clip.nr * 4);
+ }
+
+ WAIT_RING(chan, 2);
+ OUT_RING(chan, RING_3D(NV34TCL_VP_CLIP_PLANES_ENABLE, 1));
+ OUT_RING(chan, enables[nvfx->clip.nr]);
+ }
+
+ if(nvfx->use_vp_clipping && (nvfx->dirty & (NVFX_NEW_UCP | NVFX_NEW_VERTPROG)))
+ {
+ unsigned i;
+ struct nvfx_vertex_program* vp = nvfx->vertprog;
+ if(nvfx->clip.nr != vp->clip_nr)
+ {
+ unsigned idx;
+ WAIT_RING(chan, 14);
+
+ /* remove last instruction bit */
+ if(vp->clip_nr >= 0)
+ {
+ idx = vp->nr_insns - 7 + vp->clip_nr;
+ OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID, 1));
+ OUT_RING(chan, vp->exec->start + idx);
+ OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
+ OUT_RINGp (chan, vp->insns[idx].data, 4);
+ }
+
+ /* set last instruction bit */
+ idx = vp->nr_insns - 7 + nvfx->clip.nr;
+ OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_FROM_ID, 1));
+ OUT_RING(chan, vp->exec->start + idx);
+ OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_INST(0), 4));
+ OUT_RINGp(chan, vp->insns[idx].data, 3);
+ OUT_RING(chan, vp->insns[idx].data[3] | 1);
+ vp->clip_nr = nvfx->clip.nr;
+ }
+
+ // TODO: only do this for the ones changed
+ WAIT_RING(chan, 6 * 6);
+ for(i = 0; i < nvfx->clip.nr; ++i)
+ {
+ OUT_RING(chan, RING_3D(NV34TCL_VP_UPLOAD_CONST_ID, 5));
+ OUT_RING(chan, vp->data->start + i);
+ OUT_RINGp (chan, nvfx->clip.ucp[i], 4);
+ }
+ }
+
if(dirty & (NVFX_NEW_FRAGPROG | NVFX_NEW_FRAGCONST | NVFX_NEW_VERTPROG | NVFX_NEW_SPRITE))
{
nvfx_fragprog_validate(nvfx);
@@ -97,6 +165,20 @@ nvfx_state_validate_common(struct nvfx_context *nvfx)
flush_tex_cache = TRUE; // TODO: do we need this?
}
+ if(nvfx->is_nv4x)
+ {
+ unsigned vp_output = nvfx->vertprog->or | nvfx->hw_fragprog->or;
+ vp_output |= (1 << (nvfx->clip.nr + 6)) - (1 << 6);
+
+ if(vp_output != nvfx->hw_vp_output)
+ {
+ WAIT_RING(chan, 2);
+ OUT_RING(chan, RING_3D(NV40TCL_VP_RESULT_EN, 1));
+ OUT_RING(chan, vp_output);
+ nvfx->hw_vp_output = vp_output;
+ }
+ }
+
if(all_swizzled >= 0)
nvfx_framebuffer_validate(nvfx, all_swizzled);