summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/gallium/drivers/nv50/nv50_program.c19
-rw-r--r--src/gallium/drivers/nv50/nv50_program.h1
-rw-r--r--src/gallium/drivers/nv50/nv50_screen.c3
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c45
4 files changed, 64 insertions, 4 deletions
diff --git a/src/gallium/drivers/nv50/nv50_program.c b/src/gallium/drivers/nv50/nv50_program.c
index 679c28ce4b..ce3fa5fc88 100644
--- a/src/gallium/drivers/nv50/nv50_program.c
+++ b/src/gallium/drivers/nv50/nv50_program.c
@@ -159,6 +159,8 @@ struct nv50_pc {
unsigned insn_nr;
boolean allow32;
+
+ uint8_t edgeflag_out;
};
static INLINE struct nv50_reg *
@@ -2554,10 +2556,16 @@ prep_inspect_insn(struct nv50_pc *pc, const struct tgsi_full_instruction *insn)
mask = dst->WriteMask;
if (dst->File == TGSI_FILE_TEMPORARY)
- reg = pc->temp;
+ reg = pc->temp;
else
- if (dst->File == TGSI_FILE_OUTPUT)
- reg = pc->result;
+ if (dst->File == TGSI_FILE_OUTPUT) {
+ reg = pc->result;
+
+ if (insn->Instruction.Opcode == TGSI_OPCODE_MOV &&
+ dst->Index == pc->edgeflag_out &&
+ insn->Src[0].Register.File == TGSI_FILE_INPUT)
+ pc->p->cfg.edgeflag_in = insn->Src[0].Register.Index;
+ }
if (reg) {
for (c = 0; c < 4; c++) {
@@ -2856,6 +2864,9 @@ nv50_program_tx_prep(struct nv50_pc *pc)
if (p->cfg.io_nr > first)
p->cfg.io_nr = first;
break;
+ case TGSI_SEMANTIC_EDGEFLAG:
+ pc->edgeflag_out = first;
+ break;
/*
case TGSI_SEMANTIC_CLIP_DISTANCE:
p->cfg.clpd = MIN2(p->cfg.clpd, first);
@@ -3104,6 +3115,8 @@ ctor_nv50_pc(struct nv50_pc *pc, struct nv50_program *p)
p->cfg.two_side[0].hw = 0x40;
p->cfg.two_side[1].hw = 0x40;
+ p->cfg.edgeflag_in = pc->edgeflag_out = 0xff;
+
switch (p->type) {
case PIPE_SHADER_VERTEX:
p->cfg.psiz = 0x40;
diff --git a/src/gallium/drivers/nv50/nv50_program.h b/src/gallium/drivers/nv50/nv50_program.h
index 4a90c372ce..461fec1d89 100644
--- a/src/gallium/drivers/nv50/nv50_program.h
+++ b/src/gallium/drivers/nv50/nv50_program.h
@@ -58,6 +58,7 @@ struct nv50_program {
/* VP only */
uint8_t clpd, clpd_nr;
uint8_t psiz;
+ uint8_t edgeflag_in;
} cfg;
};
diff --git a/src/gallium/drivers/nv50/nv50_screen.c b/src/gallium/drivers/nv50/nv50_screen.c
index d443ca3ad0..2435f65ed2 100644
--- a/src/gallium/drivers/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nv50/nv50_screen.c
@@ -441,6 +441,9 @@ nv50_screen_create(struct pipe_winsys *ws, struct nouveau_device *dev)
so_method(so, screen->tesla, NV50TCL_SCISSOR_ENABLE, 1);
so_data (so, 1);
+ so_method(so, screen->tesla, 0x15e4, 1);
+ so_data (so, 1); /* default edgeflag to TRUE */
+
so_emit(chan, so);
so_ref (so, &screen->static_init);
so_ref (NULL, &so);
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
index f7fa0659e8..39324e30f6 100644
--- a/src/gallium/drivers/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -372,6 +372,10 @@ nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib,
so_data (so, fui(v[1]));
break;
case 1:
+ if (attrib == nv50->vertprog->cfg.edgeflag_in) {
+ so_method(so, tesla, 0x15e4, 1);
+ so_data (so, v[0] ? 1 : 0);
+ }
so_method(so, tesla, NV50TCL_VTX_ATTR_1F(attrib), 1);
so_data (so, fui(v[0]));
break;
@@ -401,6 +405,9 @@ nv50_vbo_validate(struct nv50_context *nv50)
!(nv50->vtxbuf[i].buffer->usage & PIPE_BUFFER_USAGE_VERTEX))
nv50->vbo_fifo = 0xffff;
+ if (nv50->vertprog->cfg.edgeflag_in < 16)
+ nv50->vbo_fifo = 0xffff; /* vertprog can't set edgeflag */
+
n_ve = MAX2(nv50->vtxelt_nr, nv50->state.vtxelt_nr);
vtxattr = NULL;
@@ -479,6 +486,9 @@ struct nv50_vbo_emitctx
unsigned nr_ve;
unsigned vtx_dwords;
unsigned vtx_max;
+
+ float edgeflag;
+ unsigned ve_edgeflag;
};
static INLINE void
@@ -622,6 +632,9 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit,
if (nv50_map_vbufs(nv50) == FALSE)
return FALSE;
+ emit->ve_edgeflag = nv50->vertprog->cfg.edgeflag_in;
+
+ emit->edgeflag = 0.5f;
emit->nr_ve = 0;
emit->vtx_dwords = 0;
@@ -644,7 +657,8 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit,
desc = util_format_description(ve->src_format);
assert(desc);
- size = util_format_get_component_bits(ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
+ size = util_format_get_component_bits(
+ ve->src_format, UTIL_FORMAT_COLORSPACE_RGB, 0);
assert(ve->nr_components > 0 && ve->nr_components <= 4);
@@ -686,10 +700,31 @@ emit_prepare(struct nv50_context *nv50, struct nv50_vbo_emitctx *emit,
}
emit->vtx_max = 512 / emit->vtx_dwords;
+ if (emit->ve_edgeflag < 16)
+ emit->vtx_max = 1;
return TRUE;
}
+static INLINE void
+set_edgeflag(struct nouveau_channel *chan,
+ struct nouveau_grobj *tesla,
+ struct nv50_vbo_emitctx *emit, uint32_t index)
+{
+ unsigned i = emit->ve_edgeflag;
+
+ if (i < 16) {
+ float f = *((float *)(emit->map[i] + index * emit->stride[i]));
+
+ if (emit->edgeflag != f) {
+ emit->edgeflag = f;
+
+ BEGIN_RING(chan, tesla, 0x15e4, 1);
+ OUT_RING (chan, f ? 1 : 0);
+ }
+ }
+}
+
static boolean
nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count)
{
@@ -704,6 +739,8 @@ nv50_push_arrays(struct nv50_context *nv50, unsigned start, unsigned count)
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
dw = nr * emit.vtx_dwords;
+ set_edgeflag(chan, tesla, &emit, 0); /* nr will be 1 */
+
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
for (i = 0; i < nr; ++i)
emit_vtx_next(chan, &emit);
@@ -729,6 +766,8 @@ nv50_push_elements_u32(struct nv50_context *nv50, uint32_t *map, unsigned count)
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
dw = nr * emit.vtx_dwords;
+ set_edgeflag(chan, tesla, &emit, *map);
+
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
for (i = 0; i < nr; ++i)
emit_vtx(chan, &emit, *map++);
@@ -754,6 +793,8 @@ nv50_push_elements_u16(struct nv50_context *nv50, uint16_t *map, unsigned count)
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
dw = nr * emit.vtx_dwords;
+ set_edgeflag(chan, tesla, &emit, *map);
+
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
for (i = 0; i < nr; ++i)
emit_vtx(chan, &emit, *map++);
@@ -779,6 +820,8 @@ nv50_push_elements_u08(struct nv50_context *nv50, uint8_t *map, unsigned count)
unsigned i, dw, nr = MIN2(count, emit.vtx_max);
dw = nr * emit.vtx_dwords;
+ set_edgeflag(chan, tesla, &emit, *map);
+
BEGIN_RING(chan, tesla, NV50TCL_VERTEX_DATA | 0x40000000, dw);
for (i = 0; i < nr; ++i)
emit_vtx(chan, &emit, *map++);