static boolean nv30_render_validate(struct nv30_context *nv30) { struct nv30_render *r = nv30_render(nv30->draw->render); struct nv30_rasterizer_stateobj *rast = nv30->rast; struct pipe_screen *pscreen = &nv30->screen->base.base; struct nouveau_pushbuf *push = nv30->screen->base.pushbuf; struct nouveau_object *eng3d = nv30->screen->eng3d; struct nv30_vertprog *vp = nv30->vertprog.program; struct vertex_info *vinfo = &r->vertex_info; unsigned vp_attribs = 0; unsigned vp_results = 0; unsigned attrib = 0; unsigned pntc; int i; if (!r->vertprog) { struct nouveau_heap *heap = nv30_screen(pscreen)->vp_exec_heap; if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) { while (heap->next && heap->size < 16) { struct nouveau_heap **evict = heap->next->priv; nouveau_heap_free(evict); } if (nouveau_heap_alloc(heap, 16, &r->vertprog, &r->vertprog)) return FALSE; } } vinfo->num_attribs = 0; vinfo->size = 0; /* setup routing for all necessary vp outputs */ for (i = 0; i < vp->info.num_outputs && attrib < 16; i++) { uint semantic = vp->info.output_semantic_name[i]; uint index = vp->info.output_semantic_index[i]; if (vroute_add(r, attrib, semantic, &index)) { vp_attribs |= (1 << attrib++); vp_results |= index; } } /* setup routing for replaced point coords not written by vp */ if (rast && rast->pipe.point_quad_rasterization) pntc = rast->pipe.sprite_coord_enable & 0x000002ff; else pntc = 0; while (pntc && attrib < 16) { uint index = ffs(pntc) - 1; pntc &= ~(1 << index); if (vroute_add(r, attrib, TGSI_SEMANTIC_TEXCOORD, &index)) { vp_attribs |= (1 << attrib++); vp_results |= index; } } /* modify vertex format for correct stride, and stub out unused ones */ BEGIN_NV04(push, NV30_3D(VP_UPLOAD_FROM_ID), 1); PUSH_DATA (push, r->vertprog->start); r->vtxprog[attrib - 1][3] |= 1; for (i = 0; i < attrib; i++) { BEGIN_NV04(push, NV30_3D(VP_UPLOAD_INST(0)), 4); PUSH_DATAp(push, r->vtxprog[i], 4); r->vtxfmt[i] |= vinfo->size << 8; } for (; i < 16; i++) r->vtxfmt[i] = NV30_3D_VTXFMT_TYPE_V32_FLOAT; BEGIN_NV04(push, NV30_3D(VIEWPORT_TRANSLATE_X), 8); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); PUSH_DATAf(push, 1.0); BEGIN_NV04(push, NV30_3D(DEPTH_RANGE_NEAR), 2); PUSH_DATAf(push, 0.0); PUSH_DATAf(push, 1.0); BEGIN_NV04(push, NV30_3D(VTXFMT(0)), 16); PUSH_DATAp(push, r->vtxfmt, 16); BEGIN_NV04(push, NV30_3D(VP_START_FROM_ID), 1); PUSH_DATA (push, r->vertprog->start); BEGIN_NV04(push, NV30_3D(ENGINE), 1); PUSH_DATA (push, 0x00000103); if (eng3d->oclass >= NV40_3D_CLASS) { BEGIN_NV04(push, NV40_3D(VP_ATTRIB_EN), 2); PUSH_DATA (push, vp_attribs); PUSH_DATA (push, vp_results); } vinfo->size /= 4; return TRUE; }
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; }