static void * nv30_vertex_state_create(struct pipe_context *pipe, unsigned num_elements, const struct pipe_vertex_element *elements) { struct nv30_vertex_stateobj *so; struct translate_key transkey; unsigned i; assert(num_elements); so = MALLOC(sizeof(*so) + sizeof(*so->element) * num_elements); if (!so) return NULL; memcpy(so->pipe, elements, sizeof(*elements) * num_elements); so->num_elements = num_elements; so->need_conversion = FALSE; transkey.nr_elements = 0; transkey.output_stride = 0; for (i = 0; i < num_elements; i++) { const struct pipe_vertex_element *ve = &elements[i]; const unsigned vbi = ve->vertex_buffer_index; enum pipe_format fmt = ve->src_format; so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw; if (!so->element[i].state) { switch (util_format_get_nr_components(fmt)) { case 1: fmt = PIPE_FORMAT_R32_FLOAT; break; case 2: fmt = PIPE_FORMAT_R32G32_FLOAT; break; case 3: fmt = PIPE_FORMAT_R32G32B32_FLOAT; break; case 4: fmt = PIPE_FORMAT_R32G32B32A32_FLOAT; break; default: assert(0); return NULL; } so->element[i].state = nv30_vtxfmt(pipe->screen, fmt)->hw; so->need_conversion = TRUE; } if (1) { unsigned j = transkey.nr_elements++; transkey.element[j].type = TRANSLATE_ELEMENT_NORMAL; transkey.element[j].input_format = ve->src_format; transkey.element[j].input_buffer = vbi; transkey.element[j].input_offset = ve->src_offset; transkey.element[j].instance_divisor = ve->instance_divisor; transkey.element[j].output_format = fmt; transkey.element[j].output_offset = transkey.output_stride; transkey.output_stride += (util_format_get_stride(fmt, 1) + 3) & ~3; } } so->translate = translate_create(&transkey); so->vtx_size = transkey.output_stride / 4; so->vtx_per_packet_max = NV04_PFIFO_MAX_PACKET_LEN / MAX2(so->vtx_size, 1); return so; }
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; }