void _mesa_bind_attrib_location(GLcontext *ctx, GLuint program, GLuint index, const GLchar *name) { struct gl_shader_program *shProg = _mesa_lookup_shader_program(ctx, program); const GLint size = -1; /* unknown size */ GLint i, oldIndex; if (!shProg) { _mesa_error(ctx, GL_INVALID_VALUE, "glBindAttribLocation(program)"); return; } if (!name) return; if (strncmp(name, "gl_", 3) == 0) { _mesa_error(ctx, GL_INVALID_OPERATION, "glBindAttribLocation(illegal name)"); return; } if (shProg->LinkStatus) { /* get current index/location for the attribute */ oldIndex = _mesa_get_attrib_location(ctx, program, name); } else { oldIndex = -1; } /* this will replace the current value if it's already in the list */ i = _mesa_add_attribute(shProg->Attributes, name, size, index); if (i < 0) { _mesa_error(ctx, GL_OUT_OF_MEMORY, "glBindAttribLocation"); } if (shProg->VertexProgram && oldIndex >= 0 && oldIndex != index) { /* If the index changed, need to search/replace references to that attribute * in the vertex program. */ _slang_remap_attribute(&shProg->VertexProgram->Base, oldIndex, index); } }
/** * Resolve binding of generic vertex attributes. * For example, if the vertex shader declared "attribute vec4 foobar" we'll * allocate a generic vertex attribute for "foobar" and plug that value into * the vertex program instructions. * But if the user called glBindAttributeLocation(), those bindings will * have priority. */ static GLboolean _slang_resolve_attributes(struct gl_shader_program *shProg, const struct gl_program *origProg, struct gl_program *linkedProg) { GLint attribMap[MAX_VERTEX_GENERIC_ATTRIBS]; GLuint i, j; GLbitfield usedAttributes; /* generics only, not legacy attributes */ GLbitfield inputsRead = 0x0; assert(origProg != linkedProg); assert(origProg->Target == GL_VERTEX_PROGRAM_ARB); assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB); if (!shProg->Attributes) shProg->Attributes = _mesa_new_parameter_list(); if (linkedProg->Attributes) { _mesa_free_parameter_list(linkedProg->Attributes); } linkedProg->Attributes = _mesa_new_parameter_list(); /* Build a bitmask indicating which attribute indexes have been * explicitly bound by the user with glBindAttributeLocation(). */ usedAttributes = 0x0; for (i = 0; i < shProg->Attributes->NumParameters; i++) { GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0]; usedAttributes |= (1 << attr); } /* If gl_Vertex is used, that actually counts against the limit * on generic vertex attributes. This avoids the ambiguity of * whether glVertexAttrib4fv(0, v) sets legacy attribute 0 (vert pos) * or generic attribute[0]. If gl_Vertex is used, we want the former. */ if (origProg->InputsRead & VERT_BIT_POS) { usedAttributes |= 0x1; } /* initialize the generic attribute map entries to -1 */ for (i = 0; i < MAX_VERTEX_GENERIC_ATTRIBS; i++) { attribMap[i] = -1; } /* * Scan program for generic attribute references */ for (i = 0; i < linkedProg->NumInstructions; i++) { struct prog_instruction *inst = linkedProg->Instructions + i; for (j = 0; j < 3; j++) { if (inst->SrcReg[j].File == PROGRAM_INPUT) { inputsRead |= (1 << inst->SrcReg[j].Index); } if (inst->SrcReg[j].File == PROGRAM_INPUT && inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) { /* * OK, we've found a generic vertex attribute reference. */ const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0; GLint attr = attribMap[k]; if (attr < 0) { /* Need to figure out attribute mapping now. */ const char *name = origProg->Attributes->Parameters[k].Name; const GLint size = origProg->Attributes->Parameters[k].Size; const GLenum type =origProg->Attributes->Parameters[k].DataType; GLint index; /* See if there's a user-defined attribute binding for * this name. */ index = _mesa_lookup_parameter_index(shProg->Attributes, -1, name); if (index >= 0) { /* Found a user-defined binding */ attr = shProg->Attributes->Parameters[index].StateIndexes[0]; } else { /* No user-defined binding, choose our own attribute number. * Start at 1 since generic attribute 0 always aliases * glVertex/position. */ for (attr = 0; attr < MAX_VERTEX_GENERIC_ATTRIBS; attr++) { if (((1 << attr) & usedAttributes) == 0) break; } if (attr == MAX_VERTEX_GENERIC_ATTRIBS) { link_error(shProg, "Too many vertex attributes"); return GL_FALSE; } /* mark this attribute as used */ usedAttributes |= (1 << attr); } attribMap[k] = attr; /* Save the final name->attrib binding so it can be queried * with glGetAttributeLocation(). */ _mesa_add_attribute(linkedProg->Attributes, name, size, type, attr); } assert(attr >= 0); /* update the instruction's src reg */ inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr; } } } /* Handle pre-defined attributes here (gl_Vertex, gl_Normal, etc). * When the user queries the active attributes we need to include both * the user-defined attributes and the built-in ones. */ for (i = VERT_ATTRIB_POS; i < VERT_ATTRIB_GENERIC0; i++) { if (inputsRead & (1 << i)) { _mesa_add_attribute(linkedProg->Attributes, _slang_vert_attrib_name(i), 4, /* size in floats */ _slang_vert_attrib_type(i), -1 /* attrib/input */); } } return GL_TRUE; }