- /* No? Allocate translated vp object now */
- if (!xvp) {
- xvp = ST_CALLOC_STRUCT(translated_vertex_program);
- xvp->frag_inputs = fragInputsRead;
- xvp->master = stvp;
-
- xvp->next = stfp->vertex_programs;
- stfp->vertex_programs = xvp;
- }
-
- /* See if we need to translate vertex program to TGSI form */
- if (xvp->serialNo != stvp->serialNo) {
- GLuint outAttr;
- const GLbitfield outputsWritten = stvp->Base.Base.OutputsWritten;
- GLuint numVpOuts = 0;
- GLboolean emitPntSize = GL_FALSE, emitBFC0 = GL_FALSE, emitBFC1 = GL_FALSE;
- GLbitfield usedGenerics = 0x0;
- GLbitfield usedOutputSlots = 0x0;
-
- /* Compute mapping of vertex program outputs to slots, which depends
- * on the fragment program's input->slot mapping.
- */
- for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
- /* set defaults: */
- xvp->output_to_slot[outAttr] = UNUSED;
- xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_COUNT;
- xvp->output_to_semantic_index[outAttr] = 99;
-
- if (outAttr == VERT_RESULT_HPOS) {
- /* always put xformed position into slot zero */
- GLuint slot = 0;
- xvp->output_to_slot[VERT_RESULT_HPOS] = slot;
- xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_POSITION;
- xvp->output_to_semantic_index[outAttr] = 0;
- numVpOuts++;
- usedOutputSlots |= (1 << slot);
- }
- else if (outputsWritten & (1 << outAttr)) {
- /* see if the frag prog wants this vert output */
- GLint fpInAttrib = vp_out_to_fp_in(outAttr);
- if (fpInAttrib >= 0) {
- GLuint fpInSlot = stfp->input_to_slot[fpInAttrib];
- if (fpInSlot != ~0) {
- /* match this vp output to the fp input */
- GLuint vpOutSlot = stfp->input_map[fpInSlot];
- xvp->output_to_slot[outAttr] = vpOutSlot;
- xvp->output_to_semantic_name[outAttr] = stfp->input_semantic_name[fpInSlot];
- xvp->output_to_semantic_index[outAttr] = stfp->input_semantic_index[fpInSlot];
- numVpOuts++;
- usedOutputSlots |= (1 << vpOutSlot);
- }
- else {
-#if 0 /*debug*/
- printf("VP output %d not used by FP\n", outAttr);
-#endif
- }
- }
- else if (outAttr == VERT_RESULT_PSIZ)
- emitPntSize = GL_TRUE;
- else if (outAttr == VERT_RESULT_BFC0)
- emitBFC0 = GL_TRUE;
- else if (outAttr == VERT_RESULT_BFC1)
- emitBFC1 = GL_TRUE;
- }
-#if 0 /*debug*/
- printf("assign vp output_to_slot[%d] = %d\n", outAttr,
- xvp->output_to_slot[outAttr]);
-#endif
- }
-
- /* must do these last */
- if (emitPntSize) {
- GLuint slot = numVpOuts++;
- xvp->output_to_slot[VERT_RESULT_PSIZ] = slot;
- xvp->output_to_semantic_name[VERT_RESULT_PSIZ] = TGSI_SEMANTIC_PSIZE;
- xvp->output_to_semantic_index[VERT_RESULT_PSIZ] = 0;
- usedOutputSlots |= (1 << slot);
- }
- if (emitBFC0) {
- GLuint slot = numVpOuts++;
- xvp->output_to_slot[VERT_RESULT_BFC0] = slot;
- xvp->output_to_semantic_name[VERT_RESULT_BFC0] = TGSI_SEMANTIC_COLOR;
- xvp->output_to_semantic_index[VERT_RESULT_BFC0] = 0;
- usedOutputSlots |= (1 << slot);
- }
- if (emitBFC1) {
- GLuint slot = numVpOuts++;
- xvp->output_to_slot[VERT_RESULT_BFC1] = slot;
- xvp->output_to_semantic_name[VERT_RESULT_BFC1] = TGSI_SEMANTIC_COLOR;
- xvp->output_to_semantic_index[VERT_RESULT_BFC1] = 1;
- usedOutputSlots |= (1 << slot);
- }
-
- /* build usedGenerics mask */
- usedGenerics = 0x0;
- for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
- if (xvp->output_to_semantic_name[outAttr] == TGSI_SEMANTIC_GENERIC) {
- usedGenerics |= (1 << xvp->output_to_semantic_index[outAttr]);
- }
- }
-
- /* For each vertex program output that doesn't match up to a fragment
- * program input, map the vertex program output to a free slot and
- * free generic attribute.
- */
- for (outAttr = 0; outAttr < VERT_RESULT_MAX; outAttr++) {
- if (outputsWritten & (1 << outAttr)) {
- if (xvp->output_to_slot[outAttr] == UNUSED) {
- GLint freeGeneric = _mesa_ffs(~usedGenerics) - 1;
- GLint freeSlot = _mesa_ffs(~usedOutputSlots) - 1;
- usedGenerics |= (1 << freeGeneric);
- usedOutputSlots |= (1 << freeSlot);
- xvp->output_to_slot[outAttr] = freeSlot;
- xvp->output_to_semantic_name[outAttr] = TGSI_SEMANTIC_GENERIC;
- xvp->output_to_semantic_index[outAttr] = freeGeneric;
- }
- }
-
-#if 0 /*debug*/
- printf("vp output_to_slot[%d] = %d\n", outAttr,
- xvp->output_to_slot[outAttr]);
-#endif
- }
-
- assert(stvp->Base.Base.NumInstructions > 1);
-
- st_translate_vertex_program(st, stvp, xvp->output_to_slot,
- xvp->output_to_semantic_name,
- xvp->output_to_semantic_index);
-
- xvp->vp = stvp;
-
- /* translated VP is up to date now */
- xvp->serialNo = stvp->serialNo;