static boolean vroute_add(struct nv30_render *r, uint attrib, uint sem, uint *idx) { struct nv30_screen *screen = r->nv30->screen; struct nv30_fragprog *fp = r->nv30->fragprog.program; struct vertex_info *vinfo = &r->vertex_info; enum pipe_format format; uint emit = EMIT_OMIT; uint result = *idx; if (sem == TGSI_SEMANTIC_GENERIC) { uint num_texcoords = (screen->eng3d->oclass < NV40_3D_CLASS) ? 8 : 10; for (result = 0; result < num_texcoords; result++) { if (fp->texcoord[result] == *idx + 8) { sem = TGSI_SEMANTIC_TEXCOORD; emit = vroute[sem].emit; break; } } } else { emit = vroute[sem].emit; } if (emit == EMIT_OMIT) return FALSE; draw_emit_vertex_attr(vinfo, emit, vroute[sem].interp, attrib); format = draw_translate_vinfo_format(emit); r->vtxfmt[attrib] = nv30_vtxfmt(&screen->base.base, format)->hw; r->vtxptr[attrib] = vinfo->size; vinfo->size += draw_translate_vinfo_size(emit); if (screen->eng3d->oclass < NV40_3D_CLASS) { r->vtxprog[attrib][0] = 0x001f38d8; r->vtxprog[attrib][1] = 0x0080001b | (attrib << 9); r->vtxprog[attrib][2] = 0x0836106c; r->vtxprog[attrib][3] = 0x2000f800 | (result + vroute[sem].vp30) << 2; } else { r->vtxprog[attrib][0] = 0x401f9c6c; r->vtxprog[attrib][1] = 0x0040000d | (attrib << 8); r->vtxprog[attrib][2] = 0x8106c083; r->vtxprog[attrib][3] = 0x6041ff80 | (result + vroute[sem].vp40) << 2; } if (result < 8) *idx = vroute[sem].ow40 << result; else { assert(sem == TGSI_SEMANTIC_TEXCOORD); *idx = 0x00001000 << (result - 8); } return TRUE; }
void draw_pt_emit_prepare(struct pt_emit *emit, unsigned prim, unsigned *max_vertices) { struct draw_context *draw = emit->draw; const struct vertex_info *vinfo; unsigned dst_offset; struct translate_key hw_key; unsigned i; /* XXX: need to flush to get prim_vbuf.c to release its allocation?? */ draw_do_flush( draw, DRAW_FLUSH_BACKEND ); /* XXX: may need to defensively reset this later on as clipping can * clobber this state in the render backend. */ emit->prim = prim; draw->render->set_primitive(draw->render, emit->prim); /* Must do this after set_primitive() above: */ emit->vinfo = vinfo = draw->render->get_vertex_info(draw->render); /* Translate from pipeline vertices to hw vertices. */ dst_offset = 0; for (i = 0; i < vinfo->num_attribs; i++) { unsigned emit_sz = 0; unsigned src_buffer = 0; unsigned output_format; unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) ); output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit); emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit); /* doesn't handle EMIT_OMIT */ assert(emit_sz != 0); if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) { src_buffer = 1; src_offset = 0; } hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL; hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT; hw_key.element[i].input_buffer = src_buffer; hw_key.element[i].input_offset = src_offset; hw_key.element[i].instance_divisor = 0; hw_key.element[i].output_format = output_format; hw_key.element[i].output_offset = dst_offset; dst_offset += emit_sz; } hw_key.nr_elements = vinfo->num_attribs; hw_key.output_stride = vinfo->size * 4; if (!emit->translate || translate_key_compare(&emit->translate->key, &hw_key) != 0) { translate_key_sanitize(&hw_key); emit->translate = translate_cache_find(emit->cache, &hw_key); } *max_vertices = (draw->render->max_vertex_buffer_bytes / (vinfo->size * 4)); }
static void fetch_emit_prepare( struct draw_pt_middle_end *middle, unsigned prim, unsigned opt, unsigned *max_vertices ) { struct fetch_emit_middle_end *feme = (struct fetch_emit_middle_end *)middle; struct draw_context *draw = feme->draw; const struct vertex_info *vinfo; unsigned i, dst_offset; boolean ok; struct translate_key key; unsigned gs_out_prim = (draw->gs.geometry_shader ? draw->gs.geometry_shader->output_primitive : prim); ok = draw->render->set_primitive( draw->render, gs_out_prim ); if (!ok) { assert(0); return; } /* Must do this after set_primitive() above: */ vinfo = feme->vinfo = draw->render->get_vertex_info(draw->render); /* Transform from API vertices to HW vertices, skipping the * pipeline_vertex intermediate step. */ dst_offset = 0; memset(&key, 0, sizeof(key)); for (i = 0; i < vinfo->num_attribs; i++) { const struct pipe_vertex_element *src = &draw->pt.vertex_element[vinfo->attrib[i].src_index]; unsigned emit_sz = 0; unsigned input_format = src->src_format; unsigned input_buffer = src->vertex_buffer_index; unsigned input_offset = src->src_offset; unsigned output_format; output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit); emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit); if (vinfo->attrib[i].emit == EMIT_OMIT) continue; if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) { input_format = PIPE_FORMAT_R32_FLOAT; input_buffer = draw->pt.nr_vertex_buffers; input_offset = 0; } key.element[i].type = TRANSLATE_ELEMENT_NORMAL; key.element[i].input_format = input_format; key.element[i].input_buffer = input_buffer; key.element[i].input_offset = input_offset; key.element[i].instance_divisor = src->instance_divisor; key.element[i].output_format = output_format; key.element[i].output_offset = dst_offset; dst_offset += emit_sz; } key.nr_elements = vinfo->num_attribs; key.output_stride = vinfo->size * 4; /* Don't bother with caching at this stage: */ if (!feme->translate || translate_key_compare(&feme->translate->key, &key) != 0) { translate_key_sanitize(&key); feme->translate = translate_cache_find(feme->cache, &key); feme->translate->set_buffer(feme->translate, draw->pt.nr_vertex_buffers, &feme->point_size, 0, ~0); } feme->point_size = draw->rasterizer->point_size; for (i = 0; i < draw->pt.nr_vertex_buffers; i++) { feme->translate->set_buffer(feme->translate, i, ((char *)draw->pt.user.vbuffer[i] + draw->pt.vertex_buffer[i].buffer_offset), draw->pt.vertex_buffer[i].stride, draw->pt.max_index); } *max_vertices = (draw->render->max_vertex_buffer_bytes / (vinfo->size * 4)); }
struct draw_vs_varient *draw_vs_varient_generic( struct draw_vertex_shader *vs, const struct draw_vs_varient_key *key ) { unsigned i; struct translate_key fetch, emit; struct draw_vs_varient_generic *vsvg = CALLOC_STRUCT( draw_vs_varient_generic ); if (vsvg == NULL) return NULL; vsvg->base.key = *key; vsvg->base.vs = vs; vsvg->base.set_buffer = vsvg_set_buffer; vsvg->base.run_elts = vsvg_run_elts; vsvg->base.run_linear = vsvg_run_linear; vsvg->base.destroy = vsvg_destroy; vsvg->draw = vs->draw; vsvg->temp_vertex_stride = MAX2(key->nr_inputs, vsvg->base.vs->info.num_outputs) * 4 * sizeof(float); /* Build free-standing fetch and emit functions: */ fetch.nr_elements = key->nr_inputs; fetch.output_stride = vsvg->temp_vertex_stride; for (i = 0; i < key->nr_inputs; i++) { fetch.element[i].input_format = key->element[i].in.format; fetch.element[i].input_buffer = key->element[i].in.buffer; fetch.element[i].input_offset = key->element[i].in.offset; fetch.element[i].output_format = PIPE_FORMAT_R32G32B32A32_FLOAT; fetch.element[i].output_offset = i * 4 * sizeof(float); assert(fetch.element[i].output_offset < fetch.output_stride); } emit.nr_elements = key->nr_outputs; emit.output_stride = key->output_stride; for (i = 0; i < key->nr_outputs; i++) { if (key->element[i].out.format != EMIT_1F_PSIZE) { emit.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT; emit.element[i].input_buffer = 0; emit.element[i].input_offset = key->element[i].out.vs_output * 4 * sizeof(float); emit.element[i].output_format = draw_translate_vinfo_format(key->element[i].out.format); emit.element[i].output_offset = key->element[i].out.offset; assert(emit.element[i].input_offset <= fetch.output_stride); } else { emit.element[i].input_format = PIPE_FORMAT_R32_FLOAT; emit.element[i].input_buffer = 1; emit.element[i].input_offset = 0; emit.element[i].output_format = PIPE_FORMAT_R32_FLOAT; emit.element[i].output_offset = key->element[i].out.offset; } } vsvg->fetch = draw_vs_get_fetch( vs->draw, &fetch ); vsvg->emit = draw_vs_get_emit( vs->draw, &emit ); return &vsvg->base; }
/** * Set the prim type for subsequent vertices. * This may result in a new vertex size. The existing vbuffer (if any) * will be flushed if needed and a new one allocated. */ static void vbuf_start_prim( struct vbuf_stage *vbuf, uint prim ) { struct translate_key hw_key; unsigned dst_offset; unsigned i; const struct vertex_info *vinfo; vbuf->render->set_primitive(vbuf->render, prim); /* Must do this after set_primitive() above: * * XXX: need some state managment to track when this needs to be * recalculated. The driver should tell us whether there was a * state change. */ vbuf->vinfo = vbuf->render->get_vertex_info(vbuf->render); vinfo = vbuf->vinfo; vbuf->vertex_size = vinfo->size * sizeof(float); /* Translate from pipeline vertices to hw vertices. */ dst_offset = 0; for (i = 0; i < vinfo->num_attribs; i++) { unsigned emit_sz = 0; unsigned src_buffer = 0; enum pipe_format output_format; unsigned src_offset = (vinfo->attrib[i].src_index * 4 * sizeof(float) ); output_format = draw_translate_vinfo_format(vinfo->attrib[i].emit); emit_sz = draw_translate_vinfo_size(vinfo->attrib[i].emit); /* doesn't handle EMIT_OMIT */ assert(emit_sz != 0); if (vinfo->attrib[i].emit == EMIT_1F_PSIZE) { src_buffer = 1; src_offset = 0; } else if (vinfo->attrib[i].src_index == DRAW_ATTR_NONEXIST) { /* elements which don't exist will get assigned zeros */ src_buffer = 2; src_offset = 0; } hw_key.element[i].type = TRANSLATE_ELEMENT_NORMAL; hw_key.element[i].input_format = PIPE_FORMAT_R32G32B32A32_FLOAT; hw_key.element[i].input_buffer = src_buffer; hw_key.element[i].input_offset = src_offset; hw_key.element[i].instance_divisor = 0; hw_key.element[i].output_format = output_format; hw_key.element[i].output_offset = dst_offset; dst_offset += emit_sz; } hw_key.nr_elements = vinfo->num_attribs; hw_key.output_stride = vbuf->vertex_size; /* Don't bother with caching at this stage: */ if (!vbuf->translate || translate_key_compare(&vbuf->translate->key, &hw_key) != 0) { translate_key_sanitize(&hw_key); vbuf->translate = translate_cache_find(vbuf->cache, &hw_key); vbuf->translate->set_buffer(vbuf->translate, 1, &vbuf->point_size, 0, ~0); vbuf->translate->set_buffer(vbuf->translate, 2, &vbuf->zero4[0], 0, ~0); } vbuf->point_size = vbuf->stage.draw->rasterizer->point_size; /* Allocate new buffer? */ assert(vbuf->vertices == NULL); vbuf_alloc_vertices(vbuf); }