--- 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"