[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