summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/drivers/nv50/nv50_context.h1
-rw-r--r--src/gallium/drivers/nv50/nv50_state_validate.c2
-rw-r--r--src/gallium/drivers/nv50/nv50_vbo.c73
3 files changed, 75 insertions, 1 deletions
diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h
index 5cbc2c8f82..4de6e8cfa2 100644
--- a/src/gallium/drivers/nv50/nv50_context.h
+++ b/src/gallium/drivers/nv50/nv50_context.h
@@ -120,6 +120,7 @@ struct nv50_state {
struct nouveau_stateobj *fragprog;
struct nouveau_stateobj *vtxfmt;
struct nouveau_stateobj *vtxbuf;
+ struct nouveau_stateobj *vtxattr;
};
struct nv50_context {
diff --git a/src/gallium/drivers/nv50/nv50_state_validate.c b/src/gallium/drivers/nv50/nv50_state_validate.c
index a879df2e6e..99d5b96e45 100644
--- a/src/gallium/drivers/nv50/nv50_state_validate.c
+++ b/src/gallium/drivers/nv50/nv50_state_validate.c
@@ -204,6 +204,8 @@ nv50_state_emit(struct nv50_context *nv50)
if (nv50->state.dirty & NV50_NEW_ARRAYS) {
so_emit(chan, nv50->state.vtxfmt);
so_emit(chan, nv50->state.vtxbuf);
+ if (nv50->state.vtxattr)
+ so_emit(chan, nv50->state.vtxattr);
}
nv50->state.dirty = 0;
diff --git a/src/gallium/drivers/nv50/nv50_vbo.c b/src/gallium/drivers/nv50/nv50_vbo.c
index e9975f065c..36f1b24b2f 100644
--- a/src/gallium/drivers/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nv50/nv50_vbo.c
@@ -277,17 +277,77 @@ nv50_draw_elements(struct pipe_context *pipe,
return TRUE;
}
+static INLINE boolean
+nv50_vbo_static_attrib(struct nv50_context *nv50, unsigned attrib,
+ struct nouveau_stateobj **pso,
+ struct pipe_vertex_element *ve,
+ struct pipe_vertex_buffer *vb)
+
+{
+ struct nouveau_stateobj *so;
+ struct nouveau_grobj *tesla = nv50->screen->tesla;
+ struct nouveau_bo *bo = nouveau_bo(vb->buffer);
+ float *v;
+ int ret;
+ enum pipe_format pf = ve->src_format;
+
+ if ((pf_type(pf) != PIPE_FORMAT_TYPE_FLOAT) ||
+ (pf_size_x(pf) << pf_exp2(pf)) != 32)
+ return FALSE;
+
+ ret = nouveau_bo_map(bo, NOUVEAU_BO_RD);
+ if (ret)
+ return FALSE;
+ v = (float *)(bo->map + (vb->buffer_offset + ve->src_offset));
+
+ so = *pso;
+ if (!so)
+ *pso = so = so_new(nv50->vtxelt_nr * 5, 0);
+
+ switch (ve->nr_components) {
+ case 4:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_4F_X(attrib), 4);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ so_data (so, fui(v[3]));
+ break;
+ case 3:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_3F_X(attrib), 4);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ so_data (so, fui(v[2]));
+ break;
+ case 2:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_2F_X(attrib), 4);
+ so_data (so, fui(v[0]));
+ so_data (so, fui(v[1]));
+ break;
+ case 1:
+ so_method(so, tesla, NV50TCL_VTX_ATTR_1F(attrib), 4);
+ so_data (so, fui(v[0]));
+ break;
+ default:
+ nouveau_bo_unmap(bo);
+ return FALSE;
+ }
+
+ nouveau_bo_unmap(bo);
+ return TRUE;
+}
+
void
nv50_vbo_validate(struct nv50_context *nv50)
{
struct nouveau_grobj *tesla = nv50->screen->tesla;
- struct nouveau_stateobj *vtxbuf, *vtxfmt;
+ struct nouveau_stateobj *vtxbuf, *vtxfmt, *vtxattr;
unsigned i;
/* don't validate if Gallium took away our buffers */
if (nv50->vtxbuf_nr == 0)
return;
+ vtxattr = NULL;
vtxbuf = so_new(nv50->vtxelt_nr * 7, nv50->vtxelt_nr * 4);
vtxfmt = so_new(nv50->vtxelt_nr + 1, 0);
so_method(vtxfmt, tesla, NV50TCL_VERTEX_ARRAY_ATTRIB(0),
@@ -300,6 +360,15 @@ nv50_vbo_validate(struct nv50_context *nv50)
struct nouveau_bo *bo = nouveau_bo(vb->buffer);
uint32_t hw = nv50_vbo_vtxelt_to_hw(ve);
+ if (!vb->stride &&
+ nv50_vbo_static_attrib(nv50, i, &vtxattr, ve, vb)) {
+ so_data(vtxfmt, hw | (1 << 4));
+
+ so_method(vtxbuf, tesla,
+ NV50TCL_VERTEX_ARRAY_FORMAT(i), 1);
+ so_data (vtxbuf, 0);
+ continue;
+ }
so_data(vtxfmt, hw | i);
so_method(vtxbuf, tesla, NV50TCL_VERTEX_ARRAY_FORMAT(i), 3);
@@ -323,7 +392,9 @@ nv50_vbo_validate(struct nv50_context *nv50)
so_ref (vtxfmt, &nv50->state.vtxfmt);
so_ref (vtxbuf, &nv50->state.vtxbuf);
+ so_ref (vtxattr, &nv50->state.vtxattr);
so_ref (NULL, &vtxbuf);
so_ref (NULL, &vtxfmt);
+ so_ref (NULL, &vtxattr);
}