+void GLAPIENTRY
+_mesa_GetUniformIndices(GLuint program,
+ GLsizei uniformCount,
+ const GLchar * const *uniformNames,
+ GLuint *uniformIndices)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ GLsizei i;
+ struct gl_shader_program *shProg;
+
+ if (!ctx->Extensions.ARB_uniform_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformIndices");
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glGetUniformIndices");
+ if (!shProg)
+ return;
+
+ if (uniformCount < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetUniformIndices(uniformCount < 0)");
+ return;
+ }
+
+ for (i = 0; i < uniformCount; i++) {
+ unsigned offset;
+ uniformIndices[i] = _mesa_get_uniform_location(ctx, shProg,
+ uniformNames[i], &offset);
+ }
+}
+
+void GLAPIENTRY
+_mesa_UniformBlockBinding(GLuint program,
+ GLuint uniformBlockIndex,
+ GLuint uniformBlockBinding)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+
+ if (!ctx->Extensions.ARB_uniform_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glUniformBlockBinding");
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glUniformBlockBinding");
+ if (!shProg)
+ return;
+
+ if (uniformBlockIndex >= shProg->NumUniformBlocks) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glUniformBlockBinding(block index %u >= %u)",
+ uniformBlockIndex, shProg->NumUniformBlocks);
+ return;
+ }
+
+ if (uniformBlockBinding >= ctx->Const.MaxUniformBufferBindings) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glUniformBlockBinding(block binding %u >= %u)",
+ uniformBlockBinding, ctx->Const.MaxUniformBufferBindings);
+ return;
+ }
+
+ if (shProg->UniformBlocks[uniformBlockIndex].Binding !=
+ uniformBlockBinding) {
+ int i;
+
+ FLUSH_VERTICES(ctx, 0);
+ ctx->NewDriverState |= ctx->DriverFlags.NewUniformBuffer;
+
+ shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding;
+
+ for (i = 0; i < MESA_SHADER_STAGES; i++) {
+ int stage_index = shProg->UniformBlockStageIndex[i][uniformBlockIndex];
+
+ if (stage_index != -1) {
+ struct gl_shader *sh = shProg->_LinkedShaders[i];
+ sh->UniformBlocks[stage_index].Binding = uniformBlockBinding;
+ }
+ }
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockiv(GLuint program,
+ GLuint uniformBlockIndex,
+ GLenum pname,
+ GLint *params)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+ struct gl_uniform_block *block;
+ unsigned i;
+
+ if (!ctx->Extensions.ARB_uniform_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glGetActiveUniformBlockiv");
+ if (!shProg)
+ return;
+
+ if (uniformBlockIndex >= shProg->NumUniformBlocks) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetActiveUniformBlockiv(block index %u >= %u)",
+ uniformBlockIndex, shProg->NumUniformBlocks);
+ return;
+ }
+
+ block = &shProg->UniformBlocks[uniformBlockIndex];
+
+ switch (pname) {
+ case GL_UNIFORM_BLOCK_BINDING:
+ params[0] = block->Binding;
+ return;
+
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ params[0] = block->UniformBufferSize;
+ return;
+
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ params[0] = strlen(block->Name) + 1;
+ return;
+
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ params[0] = block->NumUniforms;
+ return;
+
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ for (i = 0; i < block->NumUniforms; i++) {
+ unsigned offset;
+ params[i] = _mesa_get_uniform_location(ctx, shProg,
+ block->Uniforms[i].IndexName,
+ &offset);
+ }
+ return;
+
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_VERTEX][uniformBlockIndex] != -1;
+ return;
+
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_GEOMETRY_SHADER:
+ params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_GEOMETRY][uniformBlockIndex] != -1;
+ return;
+
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ params[0] = shProg->UniformBlockStageIndex[MESA_SHADER_FRAGMENT][uniformBlockIndex] != -1;
+ return;
+
+ default:
+ _mesa_error(ctx, GL_INVALID_ENUM,
+ "glGetActiveUniformBlockiv(pname 0x%x (%s))",
+ pname, _mesa_lookup_enum_by_nr(pname));
+ return;
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformBlockName(GLuint program,
+ GLuint uniformBlockIndex,
+ GLsizei bufSize,
+ GLsizei *length,
+ GLchar *uniformBlockName)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+ struct gl_uniform_block *block;
+
+ if (!ctx->Extensions.ARB_uniform_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
+ return;
+ }
+
+ if (bufSize < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetActiveUniformBlockName(bufSize %d < 0)",
+ bufSize);
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program,
+ "glGetActiveUniformBlockiv");
+ if (!shProg)
+ return;
+
+ if (uniformBlockIndex >= shProg->NumUniformBlocks) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetActiveUniformBlockiv(block index %u >= %u)",
+ uniformBlockIndex, shProg->NumUniformBlocks);
+ return;
+ }
+
+ block = &shProg->UniformBlocks[uniformBlockIndex];
+
+ if (uniformBlockName) {
+ _mesa_copy_string(uniformBlockName, bufSize, length, block->Name);
+ }
+}
+
+void GLAPIENTRY
+_mesa_GetActiveUniformName(GLuint program, GLuint uniformIndex,
+ GLsizei bufSize, GLsizei *length,
+ GLchar *uniformName)
+{
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg;
+
+ if (!ctx->Extensions.ARB_uniform_buffer_object) {
+ _mesa_error(ctx, GL_INVALID_OPERATION, "glGetActiveUniformBlockiv");
+ return;
+ }
+
+ if (bufSize < 0) {
+ _mesa_error(ctx, GL_INVALID_VALUE,
+ "glGetActiveUniformName(bufSize %d < 0)",
+ bufSize);
+ return;
+ }
+
+ shProg = _mesa_lookup_shader_program_err(ctx, program, "glGetActiveUniformName");
+
+ if (!shProg)
+ return;
+
+ if (uniformIndex >= shProg->NumUserUniformStorage) {
+ _mesa_error(ctx, GL_INVALID_VALUE, "glGetActiveUniform(index)");
+ return;
+ }
+
+ if (uniformName) {
+ _mesa_get_uniform_name(& shProg->UniformStorage[uniformIndex],
+ bufSize, length, uniformName);
+ }
+}