static void nv30_render_draw_elements(struct vbuf_render *render, const ushort *indices, uint count) { struct nv30_render *r = nv30_render(render); struct nv30_context *nv30 = r->nv30; struct nouveau_pushbuf *push = nv30->screen->base.pushbuf; unsigned i; BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs); for (i = 0; i < r->vertex_info.num_attribs; i++) { PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, nv04_resource(r->buffer), r->offset + r->vtxptr[i], NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } if (!nv30_state_validate(nv30, FALSE)) return; BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, r->prim); if (count & 1) { BEGIN_NV04(push, NV30_3D(VB_ELEMENT_U32), 1); PUSH_DATA (push, *indices++); } count >>= 1; while (count) { unsigned npush = MIN2(count, NV04_PFIFO_MAX_PACKET_LEN); count -= npush; BEGIN_NI04(push, NV30_3D(VB_ELEMENT_U16), npush); while (npush--) { PUSH_DATA(push, (indices[1] << 16) | indices[0]); indices += 2; } } BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_VTXTMP); }
static void nv30_update_user_vbufs(struct nv30_context *nv30) { struct nouveau_pushbuf *push = nv30->base.pushbuf; uint32_t base, offset, size; int i; uint32_t written = 0; for (i = 0; i < nv30->vertex->num_elements; i++) { struct pipe_vertex_element *ve = &nv30->vertex->pipe[i]; const int b = ve->vertex_buffer_index; struct pipe_vertex_buffer *vb = &nv30->vtxbuf[b]; struct nv04_resource *buf = nv04_resource(vb->buffer); if (!(nv30->vbo_user & (1 << b))) continue; if (!vb->stride) { nv30_emit_vtxattr(nv30, vb, ve, i); continue; } nv30_vbuf_range(nv30, b, &base, &size); if (!(written & (1 << b))) { written |= 1 << b; nouveau_user_buffer_upload(&nv30->base, buf, base, size); } offset = vb->buffer_offset + ve->src_offset; BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1); PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, buf, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } nv30->base.vbo_dirty = TRUE; }
static void nv30_render_draw_arrays(struct vbuf_render *render, unsigned start, uint nr) { struct nv30_render *r = nv30_render(render); struct nv30_context *nv30 = r->nv30; struct nouveau_pushbuf *push = nv30->base.pushbuf; unsigned fn = nr >> 8, pn = nr & 0xff; unsigned ps = fn + (pn ? 1 : 0); unsigned i; BEGIN_NV04(push, NV30_3D(VTXBUF(0)), r->vertex_info.num_attribs); for (i = 0; i < r->vertex_info.num_attribs; i++) { PUSH_RESRC(push, NV30_3D(VTXBUF(i)), BUFCTX_VTXTMP, nv04_resource(r->buffer), r->offset + r->vtxptr[i], NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } if (!nv30_state_validate(nv30, FALSE)) return; BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, r->prim); BEGIN_NI04(push, NV30_3D(VB_VERTEX_BATCH), ps); while (fn--) { PUSH_DATA (push, 0xff000000 | start); start += 256; } if (pn) PUSH_DATA (push, ((pn - 1) << 24) | start); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, NV30_3D_VERTEX_BEGIN_END_STOP); PUSH_RESET(push, BUFCTX_VTXTMP); }
void nv30_vbo_validate(struct nv30_context *nv30) { struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nv30_vertex_stateobj *vertex = nv30->vertex; struct pipe_vertex_element *ve; struct pipe_vertex_buffer *vb; unsigned i, redefine; nouveau_bufctx_reset(nv30->bufctx, BUFCTX_VTXBUF); if (!nv30->vertex || nv30->draw_flags) return; if (unlikely(vertex->need_conversion)) { nv30->vbo_fifo = ~0; nv30->vbo_user = 0; } else { nv30_prevalidate_vbufs(nv30); } if (!PUSH_SPACE(push, 128)) return; redefine = MAX2(vertex->num_elements, nv30->state.num_vtxelts); BEGIN_NV04(push, NV30_3D(VTXFMT(0)), redefine); for (i = 0; i < vertex->num_elements; i++) { ve = &vertex->pipe[i]; vb = &nv30->vtxbuf[ve->vertex_buffer_index]; if (likely(vb->stride) || nv30->vbo_fifo) PUSH_DATA (push, (vb->stride << 8) | vertex->element[i].state); else PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT); } for (; i < nv30->state.num_vtxelts; i++) { PUSH_DATA (push, NV30_3D_VTXFMT_TYPE_V32_FLOAT); } for (i = 0; i < vertex->num_elements; i++) { struct nv04_resource *res; unsigned offset; boolean user; ve = &vertex->pipe[i]; vb = &nv30->vtxbuf[ve->vertex_buffer_index]; user = (nv30->vbo_user & (1 << ve->vertex_buffer_index)); res = nv04_resource(vb->buffer); if (nv30->vbo_fifo || unlikely(vb->stride == 0)) { if (!nv30->vbo_fifo) nv30_emit_vtxattr(nv30, vb, ve, i); continue; } offset = ve->src_offset + vb->buffer_offset; BEGIN_NV04(push, NV30_3D(VTXBUF(i)), 1); PUSH_RESRC(push, NV30_3D(VTXBUF(i)), user ? BUFCTX_VTXTMP : BUFCTX_VTXBUF, res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, NV30_3D_VTXBUF_DMA1); } nv30->state.num_vtxelts = vertex->num_elements; }