nv50: use VTX_ATTR_nF for constant vtxelts
authorChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 20 Aug 2009 19:39:02 +0000 (21:39 +0200)
committerChristoph Bumiller <e0425955@student.tuwien.ac.at>
Thu, 20 Aug 2009 19:41:39 +0000 (21:41 +0200)
src/gallium/drivers/nv50/nv50_context.h
src/gallium/drivers/nv50/nv50_state_validate.c
src/gallium/drivers/nv50/nv50_vbo.c

index 5cbc2c8f823415d90032ed26f68cb441d269ac53..4de6e8cfa2968eea2265fdc0daf76df34c767d33 100644 (file)
@@ -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 {
index a879df2e6e29af1665c51b7fc9fcaf4033eef4ff..99d5b96e4563117c39b45a27e3ff0bdda7272853 100644 (file)
@@ -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;
 
index e9975f065c794e34c10cfe2afe3f672f7e87ea08..36f1b24b2f0b98415c77735c22f002f3ce912c76 100644 (file)
@@ -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);
 }