mesa: Add support for glUniformBlockBinding() and the API to get it back.
authorEric Anholt <eric@anholt.net>
Tue, 19 Jun 2012 20:43:00 +0000 (13:43 -0700)
committerEric Anholt <eric@anholt.net>
Tue, 31 Jul 2012 19:06:19 +0000 (12:06 -0700)
Fixes piglit ARB_uniform_buffer_object/uniformbufferbinding.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
src/mesa/main/uniforms.c

index ccbd753dbec78c6b355fe4b65eceeef8b3099b12..940cb07c247a61865667924d72d5d0969dc38108 100644 (file)
@@ -41,6 +41,7 @@
 #include "main/shaderapi.h"
 #include "main/shaderobj.h"
 #include "main/uniforms.h"
+#include "main/enums.h"
 #include "ir_uniform.h"
 #include "glsl_types.h"
 
@@ -583,6 +584,98 @@ _mesa_GetUniformIndices(GLuint program,
    }
 }
 
+static 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 %d >= %d)",
+                 uniformBlockIndex, shProg->NumUniformBlocks);
+      return;
+   }
+
+   if (uniformBlockBinding >= ctx->Const.MaxUniformBufferBindings) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                 "glUniformBlockBinding(block binding %d >= %d)",
+                 uniformBlockBinding, ctx->Const.MaxUniformBufferBindings);
+      return;
+   }
+
+   if (shProg->UniformBlocks[uniformBlockIndex].Binding !=
+       uniformBlockBinding) {
+      int i;
+
+      FLUSH_VERTICES(ctx, _NEW_BUFFER_OBJECT);
+      shProg->UniformBlocks[uniformBlockIndex].Binding = uniformBlockBinding;
+
+      for (i = 0; i < MESA_SHADER_TYPES; 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;
+        }
+      }
+   }
+}
+
+static 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;
+
+   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 %d >= %d)",
+                 uniformBlockIndex, shProg->NumUniformBlocks);
+      return;
+   }
+
+   block = &shProg->UniformBlocks[uniformBlockIndex];
+
+   switch (pname) {
+   case GL_UNIFORM_BLOCK_BINDING:
+      params[0] = block->Binding;
+      return;
+
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                 "glGetActiveUniformBlockiv(pname 0x%x (%s))",
+                 pname, _mesa_lookup_enum_by_nr(pname));
+      return;
+   }
+}
+
 /**
  * Plug in shader uniform-related functions into API dispatch table.
  */
@@ -644,6 +737,8 @@ _mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
    SET_GetUniformBlockIndex(exec, _mesa_GetUniformBlockIndex);
    SET_GetUniformIndices(exec, _mesa_GetUniformIndices);
    SET_GetActiveUniformsiv(exec, _mesa_GetActiveUniformsiv);
+   SET_GetActiveUniformBlockiv(exec, _mesa_GetActiveUniformBlockiv);
+   SET_UniformBlockBinding(exec, _mesa_UniformBlockBinding);
 
 #endif /* FEATURE_GL */
 }