nv40: construct vbo state the same way as the rest
authorBen Skeggs <skeggsb@gmail.com>
Mon, 25 Feb 2008 02:29:16 +0000 (13:29 +1100)
committerBen Skeggs <skeggsb@gmail.com>
Mon, 25 Feb 2008 02:30:24 +0000 (13:30 +1100)
src/gallium/drivers/nv40/nv40_context.h
src/gallium/drivers/nv40/nv40_fragtex.c
src/gallium/drivers/nv40/nv40_state.c
src/gallium/drivers/nv40/nv40_state_emit.c
src/gallium/drivers/nv40/nv40_vbo.c

index c533b9e0ef9d2e467206e46ac5b0a4f449640e2e..110d9d7ab70b8e30d56b417e68d43dc8c9640506 100644 (file)
@@ -54,7 +54,9 @@ enum nv40_state_index {
        NV40_STATE_VERTTEX1 = 28,
        NV40_STATE_VERTTEX2 = 29,
        NV40_STATE_VERTTEX3 = 30,
-       NV40_STATE_MAX = 31
+       NV40_STATE_VTXBUF = 31,
+       NV40_STATE_VTXFMT = 32,
+       NV40_STATE_MAX = 33
 };
 
 #define NV40_NEW_BLEND         (1 <<  0)
@@ -117,7 +119,7 @@ struct nv40_state {
        unsigned stipple_enabled;
        unsigned fp_samplers;
 
-       unsigned dirty;
+       uint64_t dirty;
        struct nouveau_stateobj *hw[NV40_STATE_MAX];
 };
 
@@ -149,13 +151,13 @@ struct nv40_context {
                struct pipe_blend_color blend_colour;
                struct pipe_viewport_state viewport;
                struct pipe_framebuffer_state framebuffer;
+               struct pipe_buffer *idxbuf;
+               unsigned idxbuf_format;
        } pipe_state;
 
        struct nv40_state state;
        unsigned fallback;
 
-       struct nouveau_stateobj *so_vtxbuf;
-
        struct pipe_vertex_buffer  vtxbuf[PIPE_ATTRIB_MAX];
        struct pipe_vertex_element vtxelt[PIPE_ATTRIB_MAX];
 };
@@ -208,6 +210,7 @@ extern struct nv40_state_entry nv40_state_zsa;
 extern struct nv40_state_entry nv40_state_viewport;
 extern struct nv40_state_entry nv40_state_framebuffer;
 extern struct nv40_state_entry nv40_state_fragtex;
+extern struct nv40_state_entry nv40_state_vbo;
 
 /* nv40_vbo.c */
 extern boolean nv40_draw_arrays(struct pipe_context *, unsigned mode,
index 7adee8858d01804257790fa5d62cc379a2133511..ed47d707b2f0e20c854037090c6173597e783b1b 100644 (file)
@@ -140,7 +140,7 @@ nv40_fragtex_validate(struct nv40_context *nv40)
                so_method(so, nv40->hw->curie, NV40TCL_TEX_ENABLE(unit), 1);
                so_data  (so, 0);
                so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
-               state->dirty |= (1 << (NV40_STATE_FRAGTEX0 + unit));
+               state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
        }
 
        samplers = nv40->dirty_samplers & fp->samplers;
@@ -150,7 +150,7 @@ nv40_fragtex_validate(struct nv40_context *nv40)
 
                so = nv40_fragtex_build(nv40, unit);
                so_ref(so, &nv40->state.hw[NV40_STATE_FRAGTEX0 + unit]);
-               state->dirty |= (1 << (NV40_STATE_FRAGTEX0 + unit));
+               state->dirty |= (1ULL << (NV40_STATE_FRAGTEX0 + unit));
        }
 
        nv40->state.fp_samplers = fp->samplers;
index 107e60f17983eec032c09596c65b74796581f796..e6f2754dc51964bb7af4763bc3f7a88a7f4df5a7 100644 (file)
@@ -628,7 +628,6 @@ nv40_set_vertex_buffer(struct pipe_context *pipe, unsigned index,
        struct nv40_context *nv40 = nv40_context(pipe);
 
        nv40->vtxbuf[index] = *vb;
-
        nv40->dirty |= NV40_NEW_ARRAYS;
 }
 
@@ -639,7 +638,6 @@ nv40_set_vertex_element(struct pipe_context *pipe, unsigned index,
        struct nv40_context *nv40 = nv40_context(pipe);
 
        nv40->vtxelt[index] = *ve;
-
        nv40->dirty |= NV40_NEW_ARRAYS;
 }
 
index af09ed47d6e354f6c1c91f4fd7cb42f4a2987aee..bb2ce0f7221868fc07692decc091fed0067d7599 100644 (file)
@@ -14,6 +14,7 @@ static struct nv40_state_entry *render_states[] = {
        &nv40_state_blend_colour,
        &nv40_state_zsa,
        &nv40_state_viewport,
+       &nv40_state_vbo,
        NULL
 };
 
@@ -31,7 +32,7 @@ nv40_state_validate(struct nv40_context *nv40)
 
                if (nv40->dirty & e->dirty.pipe) {
                        if (e->validate(nv40))
-                               nv40->state.dirty |= (1 << e->dirty.hw);
+                               nv40->state.dirty |= (1ULL << e->dirty.hw);
                }
 
                states++;
@@ -64,20 +65,21 @@ nv40_state_emit(struct nv40_context *nv40)
        unsigned i, samplers;
 
        while (state->dirty) {
-               unsigned idx = ffs(state->dirty) - 1;
+               unsigned idx = ffsll(state->dirty) - 1;
 
                so_ref (state->hw[idx], &nv40->hw->state[idx]);
                so_emit(nv40->nvws, nv40->hw->state[idx]);
-               state->dirty &= ~(1 << idx);
+               state->dirty &= ~(1ULL << idx);
        }
 
        so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FB]);
        for (i = 0, samplers = state->fp_samplers; i < 16 && samplers; i++) {
                so_emit_reloc_markers(nv40->nvws,
                                      state->hw[NV40_STATE_FRAGTEX0+i]);
-               samplers &= ~(1 << i);
+               samplers &= ~(1ULL << i);
        }
        so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_FRAGPROG]);
+       so_emit_reloc_markers(nv40->nvws, state->hw[NV40_STATE_VTXBUF]);
 }
 
 void
index 753c2fe64b9e4ec60c0663677bc4daf4c24bf58c..b5faf06291c071777fad6985aa84dbf46474df7e 100644 (file)
@@ -39,6 +39,43 @@ nv40_vbo_type(uint format)
        }
 }
 
+static boolean
+nv40_vbo_set_idxbuf(struct nv40_context *nv40, struct pipe_buffer *ib,
+                   unsigned ib_size)
+{
+       unsigned type;
+
+       if (!ib) {
+               nv40->pipe_state.idxbuf = NULL;
+               nv40->pipe_state.idxbuf_format = 0xdeadbeef;
+               return FALSE;
+       }
+
+       /* No support for 8bit indices, no support at all on 0x4497 chips */
+       if (nv40->hw->curie->grclass == NV44TCL || ib_size == 1)
+               return FALSE;
+
+       switch (ib_size) {
+       case 2:
+               type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
+               break;
+       case 4:
+               type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
+               break;
+       default:
+               return FALSE;
+       }
+
+       if (ib != nv40->pipe_state.idxbuf ||
+           type != nv40->pipe_state.idxbuf_format) {
+               nv40->dirty |= NV40_NEW_ARRAYS;
+               nv40->pipe_state.idxbuf = ib;
+               nv40->pipe_state.idxbuf_format = type;
+       }
+
+       return TRUE;
+}
+
 static boolean
 nv40_vbo_static_attrib(struct nv40_context *nv40, int attrib,
                       struct pipe_vertex_element *ve,
@@ -101,104 +138,15 @@ nv40_vbo_static_attrib(struct nv40_context *nv40, int attrib,
        return TRUE;
 }
 
-static void
-nv40_vbo_arrays_update(struct nv40_context *nv40, struct pipe_buffer *ib,
-                      unsigned ib_format)
-{
-       struct nv40_vertex_program *vp = nv40->pipe_state.vertprog;
-       struct nouveau_stateobj *vtxbuf, *vtxfmt;
-       unsigned inputs, hw, num_hw;
-       unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
-
-       inputs = vp->ir;
-       for (hw = 0; hw < 16 && inputs; hw++) {
-               if (inputs & (1 << hw)) {
-                       num_hw = hw;
-                       inputs &= ~(1 << hw);
-               }
-       }
-       num_hw++;
-
-       vtxbuf = so_new(20, 18);
-       so_method(vtxbuf, nv40->hw->curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
-       vtxfmt = so_new(17, 0);
-       so_method(vtxfmt, nv40->hw->curie, NV40TCL_VTXFMT(0), num_hw);
-
-       inputs = vp->ir;
-       for (hw = 0; hw < num_hw; hw++) {
-               struct pipe_vertex_element *ve;
-               struct pipe_vertex_buffer *vb;
-
-               if (!(inputs & (1 << hw))) {
-                       so_data(vtxbuf, 0);
-                       so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
-                       continue;
-               }
-
-               ve = &nv40->vtxelt[hw];
-               vb = &nv40->vtxbuf[ve->vertex_buffer_index];
-
-               if (!vb->pitch && nv40_vbo_static_attrib(nv40, hw, ve, vb)) {
-                       so_data(vtxbuf, 0);
-                       so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
-                       continue;
-               }
-
-               so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
-                        vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
-                        0, NV40TCL_VTXBUF_ADDRESS_DMA1);
-               so_data (vtxfmt, ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
-                                 (nv40_vbo_ncomp(ve->src_format) <<
-                                  NV40TCL_VTXFMT_SIZE_SHIFT) |
-                                 nv40_vbo_type(ve->src_format)));
-       }
-
-       if (ib) {
-               so_method(vtxbuf, nv40->hw->curie, NV40TCL_IDXBUF_ADDRESS, 2);
-               so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
-               so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
-                         0, NV40TCL_IDXBUF_FORMAT_DMA1);
-       }
-
-       so_emit(nv40->nvws, vtxfmt);
-       so_emit(nv40->nvws, vtxbuf);
-       so_ref (vtxbuf, &nv40->so_vtxbuf);
-       so_ref (NULL, &vtxfmt);
-}
-
-static boolean
-nv40_vbo_validate_state(struct nv40_context *nv40,
-                       struct pipe_buffer *ib, unsigned ib_format)
-{
-       unsigned vdn = nv40->dirty & NV40_NEW_ARRAYS;
-
-       nv40_emit_hw_state(nv40);
-       if (vdn || ib) {
-               nv40_vbo_arrays_update(nv40, ib, ib_format);
-               nv40->dirty &= ~NV40_NEW_ARRAYS;
-       }
-
-       so_emit_reloc_markers(nv40->nvws, nv40->so_vtxbuf);
-
-       BEGIN_RING(curie, 0x1710, 1);
-       OUT_RING  (0); /* vtx cache flush */
-
-       return TRUE;
-}
-
 boolean
 nv40_draw_arrays(struct pipe_context *pipe, unsigned mode, unsigned start,
                 unsigned count)
 {
        struct nv40_context *nv40 = nv40_context(pipe);
        unsigned nr;
-       boolean ret;
 
-       ret = nv40_vbo_validate_state(nv40, NULL, 0);
-       if (!ret) {
-               NOUVEAU_ERR("state validate failed\n");
-               return FALSE;
-       }
+       nv40_vbo_set_idxbuf(nv40, NULL, 0);
+       nv40_emit_hw_state(nv40);
 
        BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
        OUT_RING  (nvgl_primitive(mode));
@@ -305,14 +253,9 @@ nv40_draw_elements_inline(struct pipe_context *pipe,
 {
        struct nv40_context *nv40 = nv40_context(pipe);
        struct pipe_winsys *ws = pipe->winsys;
-       boolean ret;
        void *map;
 
-       ret = nv40_vbo_validate_state(nv40, NULL, 0);
-       if (!ret) {
-               NOUVEAU_ERR("state validate failed\n");
-               return FALSE;
-       }
+       nv40_emit_hw_state(nv40);
 
        map = ws->buffer_map(ws, ib, PIPE_BUFFER_USAGE_CPU_READ);
        if (!ib) {
@@ -348,30 +291,12 @@ nv40_draw_elements_inline(struct pipe_context *pipe,
 
 static boolean
 nv40_draw_elements_vbo(struct pipe_context *pipe,
-                      struct pipe_buffer *ib, unsigned ib_size,
                       unsigned mode, unsigned start, unsigned count)
 {
        struct nv40_context *nv40 = nv40_context(pipe);
-       unsigned nr, type;
-       boolean ret;
-
-       switch (ib_size) {
-       case 2:
-               type = NV40TCL_IDXBUF_FORMAT_TYPE_U16;
-               break;
-       case 4:
-               type = NV40TCL_IDXBUF_FORMAT_TYPE_U32;
-               break;
-       default:
-               NOUVEAU_ERR("invalid idxbuf fmt %d\n", ib_size);
-               return FALSE;
-       }
+       unsigned nr;
 
-       ret = nv40_vbo_validate_state(nv40, ib, type);
-       if (!ret) {
-               NOUVEAU_ERR("failed state validation\n");
-               return FALSE;
-       }
+       nv40_emit_hw_state(nv40);
 
        BEGIN_RING(curie, NV40TCL_BEGIN_END, 1);
        OUT_RING  (nvgl_primitive(mode));
@@ -409,19 +334,92 @@ nv40_draw_elements(struct pipe_context *pipe,
 {
        struct nv40_context *nv40 = nv40_context(pipe);
 
-       /* 0x4497 doesn't support real index buffers, and there doesn't appear
-        * to be support on any chipset for 8-bit indices.
-        */
-       if (nv40->hw->curie->grclass == NV44TCL || indexSize == 1) {
+       if (nv40_vbo_set_idxbuf(nv40, indexBuffer, indexSize)) {
+               nv40_draw_elements_vbo(pipe, mode, start, count);
+       } else {
                nv40_draw_elements_inline(pipe, indexBuffer, indexSize,
                                          mode, start, count);
-       } else {
-               nv40_draw_elements_vbo(pipe, indexBuffer, indexSize,
-                                      mode, start, count);
        }
 
        pipe->flush(pipe, 0);
        return TRUE;
 }
 
+static boolean
+nv40_vbo_validate(struct nv40_context *nv40)
+{
+       struct nv40_vertex_program *vp = nv40->pipe_state.vertprog;
+       struct nouveau_stateobj *vtxbuf, *vtxfmt;
+       struct pipe_buffer *ib = nv40->pipe_state.idxbuf;
+       unsigned ib_format = nv40->pipe_state.idxbuf_format;
+       unsigned inputs, hw, num_hw;
+       unsigned vb_flags = NOUVEAU_BO_VRAM | NOUVEAU_BO_GART | NOUVEAU_BO_RD;
+
+       inputs = vp->ir;
+       for (hw = 0; hw < 16 && inputs; hw++) {
+               if (inputs & (1 << hw)) {
+                       num_hw = hw;
+                       inputs &= ~(1 << hw);
+               }
+       }
+       num_hw++;
+
+       vtxbuf = so_new(20, 18);
+       so_method(vtxbuf, nv40->hw->curie, NV40TCL_VTXBUF_ADDRESS(0), num_hw);
+       vtxfmt = so_new(17, 0);
+       so_method(vtxfmt, nv40->hw->curie, NV40TCL_VTXFMT(0), num_hw);
+
+       inputs = vp->ir;
+       for (hw = 0; hw < num_hw; hw++) {
+               struct pipe_vertex_element *ve;
+               struct pipe_vertex_buffer *vb;
+
+               if (!(inputs & (1 << hw))) {
+                       so_data(vtxbuf, 0);
+                       so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
+                       continue;
+               }
+
+               ve = &nv40->vtxelt[hw];
+               vb = &nv40->vtxbuf[ve->vertex_buffer_index];
+
+               if (!vb->pitch && nv40_vbo_static_attrib(nv40, hw, ve, vb)) {
+                       so_data(vtxbuf, 0);
+                       so_data(vtxfmt, NV40TCL_VTXFMT_TYPE_FLOAT);
+                       continue;
+               }
+
+               so_reloc(vtxbuf, vb->buffer, vb->buffer_offset + ve->src_offset,
+                        vb_flags | NOUVEAU_BO_LOW | NOUVEAU_BO_OR,
+                        0, NV40TCL_VTXBUF_ADDRESS_DMA1);
+               so_data (vtxfmt, ((vb->pitch << NV40TCL_VTXFMT_STRIDE_SHIFT) |
+                                 (nv40_vbo_ncomp(ve->src_format) <<
+                                  NV40TCL_VTXFMT_SIZE_SHIFT) |
+                                 nv40_vbo_type(ve->src_format)));
+       }
+
+       if (ib) {
+               so_method(vtxbuf, nv40->hw->curie, NV40TCL_IDXBUF_ADDRESS, 2);
+               so_reloc (vtxbuf, ib, 0, vb_flags | NOUVEAU_BO_LOW, 0, 0);
+               so_reloc (vtxbuf, ib, ib_format, vb_flags | NOUVEAU_BO_OR,
+                         0, NV40TCL_IDXBUF_FORMAT_DMA1);
+       }
+
+       so_method(vtxbuf, nv40->hw->curie, 0x1710, 1);
+       so_data  (vtxbuf, 0);
+
+       so_ref(vtxbuf, &nv40->state.hw[NV40_STATE_VTXBUF]);
+       nv40->state.dirty |= (1ULL << NV40_STATE_VTXBUF);
+       so_ref(vtxfmt, &nv40->state.hw[NV40_STATE_VTXFMT]);
+       nv40->state.dirty |= (1ULL << NV40_STATE_VTXFMT);
+       return FALSE;
+}
+
+struct nv40_state_entry nv40_state_vbo = {
+       .validate = nv40_vbo_validate,
+       .dirty = {
+               .pipe = NV40_NEW_ARRAYS,
+               .hw = 0,
+       }
+};