/** * Checks if array subscript is valid and if so sets array_index. */ static bool valid_array_index(const GLchar *name, unsigned *array_index) { long idx = 0; const GLchar *out_base_name_end; idx = parse_program_resource_name(name, &out_base_name_end); if (idx < 0) return false; if (array_index) *array_index = idx; return true; }
/** * Called via glGetUniformLocation(). * * Returns the uniform index into UniformStorage (also the * glGetActiveUniformsiv uniform index), and stores the referenced * array offset in *offset, or GL_INVALID_INDEX (-1). */ extern "C" unsigned _mesa_get_uniform_location(struct gl_shader_program *shProg, const GLchar *name, unsigned *out_offset) { /* Page 80 (page 94 of the PDF) of the OpenGL 2.1 spec says: * * "The first element of a uniform array is identified using the * name of the uniform array appended with "[0]". Except if the last * part of the string name indicates a uniform array, then the * location of the first element of that array can be retrieved by * either using the name of the uniform array, or the name of the * uniform array appended with "[0]"." * * Note: since uniform names are not allowed to use whitespace, and array * indices within uniform names are not allowed to use "+", "-", or leading * zeros, it follows that each uniform has a unique name up to the possible * ambiguity with "[0]" noted above. Therefore we don't need to worry * about mal-formed inputs--they will properly fail when we try to look up * the uniform name in shProg->UniformHash. */ const GLchar *base_name_end; long offset = parse_program_resource_name(name, &base_name_end); bool array_lookup = offset >= 0; char *name_copy; if (array_lookup) { name_copy = (char *) malloc(base_name_end - name + 1); memcpy(name_copy, name, base_name_end - name); name_copy[base_name_end - name] = '\0'; } else { name_copy = (char *) name; offset = 0; } unsigned location = 0; const bool found = shProg->UniformHash->get(location, name_copy); assert(!found || strcmp(name_copy, shProg->UniformStorage[location].name) == 0); /* Free the temporary buffer *before* possibly returning an error. */ if (name_copy != name) free(name_copy); if (!found) return GL_INVALID_INDEX; /* If the uniform is an array, fail if the index is out of bounds. * (A negative index is caught above.) This also fails if the uniform * is not an array, but the user is trying to index it, because * array_elements is zero and offset >= 0. */ if (array_lookup && offset >= (long) shProg->UniformStorage[location].array_elements) { return GL_INVALID_INDEX; } *out_offset = offset; return location; }