[PATCH] nv50: support for user clip planes

Christoph Bumiller e0425955 at student.tuwien.ac.at
Sun Jun 21 09:25:25 PDT 2009


---
 src/gallium/drivers/nv50/nv50_context.h |    1 +
 src/gallium/drivers/nv50/nv50_program.c |   95 ++++++++++++++++++++++++++++---
 src/gallium/drivers/nv50/nv50_program.h |    2 +
 src/gallium/drivers/nv50/nv50_state.c   |    4 +
 4 files changed, 94 insertions(+), 8 deletions(-)

diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index aadcfda..1738000 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -140,6 +140,7 @@ struct nv50_context {
 	struct pipe_poly_stipple stipple;
 	struct pipe_scissor_state scissor;
 	struct pipe_viewport_state viewport;
+	struct pipe_clip_state clip;
 	struct pipe_framebuffer_state framebuffer;
 	struct nv50_program *vertprog;
 	struct nv50_program *fragprog;
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 5fae325..74f5cff 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -117,6 +117,8 @@ struct nv50_pc {
 	struct nv50_reg *iv_p;
 	struct nv50_reg *iv_c;
 
+	struct nv50_reg r_hpos[4];
+
 	/* current instruction and total number of insns */
 	unsigned insn_cur;
 	unsigned insn_nr;
@@ -2015,7 +2017,7 @@ nv50_program_tx_prep(struct nv50_pc *pc)
 	}
 
 	if (pc->result_nr) {
-		unsigned nr = pc->result_nr * 4 /* + nr of clip planes */;
+		unsigned nr = pc->result_nr * 4 + pc->p->cfg.vp.ucp.nr;
 		int rid = 0;
 
 		pc->result = MALLOC(nr * sizeof(struct nv50_reg));
@@ -2026,6 +2028,14 @@ nv50_program_tx_prep(struct nv50_pc *pc)
 			for (i = 0; i < nr; i++)
 				ctor_reg(&pc->result[i], P_RESULT, i / 4, i);
 
+			if (pc->p->cfg.vp.ucp.nr) {
+				for (c = 0; c < 4; c++) {
+					pc->r_hpos[c] = pc->result[c];
+					pc->result[c].type = P_TEMP;
+					pc->result[c].hw = -1;
+				}
+			}
+
 			/* output id offset bcol from fcol */
 			if (bcol[0] != 0xffff)
 				pc->p->cfg.vp.bcol = bcol[0] - fcol[0];
@@ -2113,6 +2123,8 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
 
 	switch (p->type) {
 	case PIPE_SHADER_VERTEX:
+		pc->param_nr += p->cfg.vp.ucp.nr;
+		pc->p->cfg.vp.clip_ctrl = 0;
 		break;
 	case PIPE_SHADER_FRAGMENT:
 		p->cfg.fp.regs[0] = 0x01000404;
@@ -2143,6 +2155,27 @@ nv50fp_move_outputs(struct nv50_pc *pc)
 	}
 }
 
+static void
+nv50vp_ucp_append(struct nv50_pc *pc)
+{
+	struct nv50_reg clpd, temp, *hpos = &pc->result[0];
+	unsigned i, k = (pc->param_nr - pc->p->cfg.vp.ucp.nr) * 4;
+
+	ctor_reg(&temp, P_TEMP, -1, -1);
+	ctor_reg(&clpd, P_RESULT, -1, pc->result_nr * 4);
+
+	for (i = 0; i < pc->p->cfg.vp.ucp.nr; i++, clpd.hw++) {
+		emit_mul(pc, &temp, &hpos[0], &pc->param[k++]);
+		emit_mad(pc, &temp, &hpos[1], &pc->param[k++], &temp);
+		emit_mad(pc, &temp, &hpos[2], &pc->param[k++], &temp);
+		emit_mad(pc, &clpd, &hpos[3], &pc->param[k++], &temp);
+		pc->p->cfg.vp.clip_ctrl |= (1 << i);
+	}
+
+	for (i = 0; i < 4; i++)
+		emit_mov(pc, &pc->r_hpos[i], &hpos[i]);
+}
+
 static void nv50_program_tx_postprocess(struct nv50_pc *pc)
 {
 	struct nv50_program_exec *e, *e_prev = NULL;
@@ -2150,6 +2183,9 @@ static void nv50_program_tx_postprocess(struct nv50_pc *pc)
 
 	if (pc->p->type == PIPE_SHADER_FRAGMENT)
 		nv50fp_move_outputs(pc);
+	else
+	if (pc->p->type == PIPE_SHADER_VERTEX)
+		nv50vp_ucp_append(pc);
 
 	for (e = pc->p->exec_head, pos = 0; e; e = e->next) {
 		pos += is_long(e) ? 2 : 1;
@@ -2259,6 +2295,7 @@ static void
 nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
 {
 	struct pipe_screen *pscreen = nv50->pipe.screen;
+	unsigned cbuf, start, count;
 
 	if (!p->data[0] && p->immd_nr) {
 		struct nouveau_resource *heap = nv50->screen->immd_heap[0];
@@ -2279,7 +2316,10 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
 					 p->immd_nr, NV50_CB_PMISC);
 	}
 
-	if (!p->data[1] && p->param_nr) {
+	if (!p->param_nr)
+		return;
+
+	if (!p->data[1]) {
 		struct nouveau_resource *heap =
 			nv50->screen->parm_heap[p->type];
 
@@ -2295,16 +2335,29 @@ nv50_program_validate_data(struct nv50_context *nv50, struct nv50_program *p)
 		}
 	}
 
-	if (p->param_nr) {
-		unsigned cbuf = NV50_CB_PVP;
+	start = p->data[1]->start;
+
+	if (p->type == PIPE_SHADER_VERTEX) {
+		count = p->param_nr - p->cfg.vp.ucp.nr * 4;
+		cbuf = NV50_CB_PVP;
+	} else {
+		count = p->param_nr;
+		cbuf = NV50_CB_PFP;
+	}
+
+	if (count) {
 		float *map = pipe_buffer_map(pscreen, nv50->constbuf[p->type],
 					     PIPE_BUFFER_USAGE_CPU_READ);
-		if (p->type == PIPE_SHADER_FRAGMENT)
-			cbuf = NV50_CB_PFP;
-		nv50_program_upload_data(nv50, map, p->data[1]->start,
-					 p->param_nr, cbuf);
+		nv50_program_upload_data(nv50, map, start, count, cbuf);
 		pipe_buffer_unmap(pscreen, nv50->constbuf[p->type]);
 	}
+
+	if (p->param_nr > count) {
+		start += count;
+		count = p->cfg.vp.ucp.nr * 4;
+		nv50_program_upload_data(nv50, &p->cfg.vp.ucp.ucp[0][0],
+					 start, count, cbuf);
+	}
 }
 
 static void
@@ -2398,6 +2451,12 @@ nv50_vertprog_validate(struct nv50_context *nv50)
 	struct nv50_program *p = nv50->vertprog;
 	struct nouveau_stateobj *so;
 
+	if (p->translated && p->cfg.vp.ucp.nr != nv50->clip.nr)
+		nv50_program_destroy(nv50, p);
+
+	if (nv50->clip.nr)
+		memcpy(&p->cfg.vp.ucp, &nv50->clip, sizeof(nv50->clip));
+
 	if (!p->translated) {
 		nv50_program_validate(nv50, p);
 		if (!p->translated)
@@ -2532,6 +2591,7 @@ nv50_linkage_create(struct nv50_context *nv50)
 	struct nouveau_grobj *tesla = nv50->screen->tesla;
 	struct nv50_program *vp = nv50->vertprog;
 	struct nv50_program *fp = nv50->fragprog;
+	struct pipe_clip_state *ucp = &vp->cfg.vp.ucp;
 	struct nouveau_stateobj *so = so_new(32, 0);
 
 	uint32_t regs[5];
@@ -2546,6 +2606,21 @@ nv50_linkage_create(struct nv50_context *nv50)
 	regs[0] /* 1904 */ = fp->cfg.fp.regs[0];
 	regs[4] /* 1988 */ = fp->cfg.fp.regs[1];
 
+	if (ucp->nr) {
+		n = vp->cfg.high_result - ucp->nr;
+		m += ucp->nr;
+
+		map[1] = 0x03020100 + (0x01010101 * n);
+		map[2] = 0x07060504 + (0x01010101 * n);
+
+		regs[1] |= (m << 8);
+		regs[0] += (ucp->nr << 8) + ucp->nr;
+		regs[4] += (ucp->nr << 8);
+	}
+
+	so_method(so, tesla, 0x1510, 1);
+	so_data  (so, vp->cfg.vp.clip_ctrl);
+
 	so_method(so, tesla, 0x1688, 1);
 
 	if (nv50->rasterizer->pipe.light_twoside) {
@@ -2606,6 +2681,8 @@ void nv50_linkage_validate(struct nv50_context *nv50)
 
 	cfg = nv50->rasterizer->pipe.light_twoside;
 	cfg |= nv50->rasterizer->pipe.point_size_per_vertex << 1;
+	if (nv50->clip.nr)
+		cfg |= (1 << 2);
 
 	if (vp->ln) {
 		it = vp->ln->next[0];
@@ -2647,6 +2724,8 @@ nv50_program_destroy(struct nv50_context *nv50, struct nv50_program *p)
 	while (p->ln)
 		program_del_linkage(p->ln);
 
+	p->cfg.vp.ucp.nr = 0;
+
 	p->translated = 0;
 }
 
diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h
index 6478338..bd28d21 100644
--- a/src/gallium/drivers/nv50/nv50_program.h
+++ b/src/gallium/drivers/nv50/nv50_program.h
@@ -50,6 +50,8 @@ struct nv50_program {
 		struct {
 			unsigned attr[2];
 			unsigned bcol;
+			unsigned clip_ctrl;
+			struct pipe_clip_state ucp;
 		} vp;
 		struct {
 			unsigned regs[4];
diff --git a/src/gallium/drivers/nv50/nv50_state.c b/src/gallium/drivers/nv50/nv50_state.c
index 116866a..4fab820 100644
--- a/src/gallium/drivers/nv50/nv50_state.c
+++ b/src/gallium/drivers/nv50/nv50_state.c
@@ -549,6 +549,10 @@ static void
 nv50_set_clip_state(struct pipe_context *pipe,
 		    const struct pipe_clip_state *clip)
 {
+	struct nv50_context *nv50 = nv50_context(pipe);
+
+	nv50->clip = *clip;
+	nv50->dirty |= NV50_NEW_VERTPROG_CB;
 }
 
 static void
-- 
1.6.0.6


--------------090503050107050804030002
Content-Type: text/plain;
 name="0010-nv50-support-point_size_per_vertex.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="0010-nv50-support-point_size_per_vertex.patch"



More information about the Nouveau mailing list