static void nv30_draw_elements(struct nv30_context *nv30, boolean shorten, unsigned mode, unsigned start, unsigned count, unsigned instance_count, int32_t index_bias) { const unsigned index_size = nv30->idxbuf.index_size; struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; unsigned prim = nv30_prim_gl(mode); #if 0 /*XXX*/ if (index_bias != nv30->state.index_bias) { BEGIN_NV04(push, NV30_3D(VB_ELEMENT_BASE), 1); PUSH_DATA (push, index_bias); nv30->state.index_bias = index_bias; } #endif if (eng3d->oclass == NV40_3D_CLASS && index_size > 1 && nv30->idxbuf.buffer) { struct nv04_resource *res = nv04_resource(nv30->idxbuf.buffer); unsigned offset = nv30->idxbuf.offset; assert(nouveau_resource_mapped_by_gpu(&res->base)); BEGIN_NV04(push, NV30_3D(IDXBUF_OFFSET), 2); PUSH_RESRC(push, NV30_3D(IDXBUF_OFFSET), BUFCTX_IDXBUF, res, offset, NOUVEAU_BO_LOW | NOUVEAU_BO_RD, 0, 0); PUSH_MTHD (push, NV30_3D(IDXBUF_FORMAT), BUFCTX_IDXBUF, res->bo, (index_size == 2) ? 0x00000010 : 0x00000000, res->domain | NOUVEAU_BO_RD, 0, NV30_3D_IDXBUF_FORMAT_DMA1); BEGIN_NV04(push, NV30_3D(VERTEX_BEGIN_END), 1); PUSH_DATA (push, prim); while (count) { const unsigned mpush = 2047 * 256; unsigned npush = (count > mpush) ? mpush : count; unsigned wpush = ((npush + 255) & ~255) >> 8; count -= npush; BEGIN_NI04(push, NV30_3D(VB_INDEX_BATCH), wpush); while (npush >= 256) { PUSH_DATA (push, 0xff000000 | start); start += 256; npush -= 256; } if (npush) PUSH_DATA (push, ((npush - 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_IDXBUF); } else {
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; }
void nv30_fragprog_validate(struct nv30_context *nv30) { struct nouveau_pushbuf *push = nv30->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nv30_fragprog *fp = nv30->fragprog.program; bool upload = false; int i; if (!fp->translated) { _nvfx_fragprog_translate(eng3d->oclass, fp); if (!fp->translated) return; upload = true; } /* update constants, also needs to be done on every fp switch as we * have no idea whether the constbuf changed in the meantime */ if (nv30->fragprog.constbuf) { struct pipe_resource *constbuf = nv30->fragprog.constbuf; uint32_t *cbuf = (uint32_t *)nv04_resource(constbuf)->data; for (i = 0; i < fp->nr_consts; i++) { unsigned off = fp->consts[i].offset; unsigned idx = fp->consts[i].index * 4; if (!memcmp(&fp->insn[off], &cbuf[idx], 4 * 4)) continue; memcpy(&fp->insn[off], &cbuf[idx], 4 * 4); upload = true; } } if (upload) nv30_fragprog_upload(nv30); /* FP_ACTIVE_PROGRAM needs to be done again even if only the consts * were updated. TEX_CACHE_CTL magic is not enough to convince the * GPU that it should re-read the fragprog from VRAM... sigh. */ if (nv30->state.fragprog != fp || upload) { struct nv04_resource *r = nv04_resource(fp->buffer); if (!PUSH_SPACE(push, 8)) return; PUSH_RESET(push, BUFCTX_FRAGPROG); BEGIN_NV04(push, NV30_3D(FP_ACTIVE_PROGRAM), 1); PUSH_RESRC(push, NV30_3D(FP_ACTIVE_PROGRAM), BUFCTX_FRAGPROG, r, 0, NOUVEAU_BO_LOW | NOUVEAU_BO_RD | NOUVEAU_BO_OR, NV30_3D_FP_ACTIVE_PROGRAM_DMA0, NV30_3D_FP_ACTIVE_PROGRAM_DMA1); BEGIN_NV04(push, NV30_3D(FP_CONTROL), 1); PUSH_DATA (push, fp->fp_control); if (eng3d->oclass < NV40_3D_CLASS) { BEGIN_NV04(push, NV30_3D(FP_REG_CONTROL), 1); PUSH_DATA (push, 0x00010004); BEGIN_NV04(push, NV30_3D(TEX_UNITS_ENABLE), 1); PUSH_DATA (push, fp->texcoords); } else { BEGIN_NV04(push, SUBC_3D(0x0b40), 1); PUSH_DATA (push, 0x00000000); } nv30->state.fragprog = fp; } }