mesa: add & use a new driver flag for UBO updates instead of _NEW_BUFFER_OBJECT
[mesa.git] / src / mesa / main / uniforms.c
index e6604b1a4c65c08609f654913f2d409cdd319298..f0d80f0c81212d247bbd6cbeb6c615f96dfd3d19 100644 (file)
  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
- * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
  */
 
 /**
@@ -41,6 +42,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"
 
@@ -98,7 +100,7 @@ _mesa_uniform_attach_driver_storage(struct gl_uniform_storage *uni,
                                    enum gl_uniform_driver_format format,
                                    void *data)
 {
-   uni->driver_storage = (struct gl_uniform_driver_storage*)
+   uni->driver_storage =
       realloc(uni->driver_storage,
              sizeof(struct gl_uniform_driver_storage)
              * (uni->num_driver_storage + 1));
@@ -127,14 +129,14 @@ _mesa_uniform_detach_all_driver_storage(struct gl_uniform_storage *uni)
 }
 
 void GLAPIENTRY
-_mesa_Uniform1fARB(GLint location, GLfloat v0)
+_mesa_Uniform1f(GLint location, GLfloat v0)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_FLOAT);
 }
 
 void GLAPIENTRY
-_mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
+_mesa_Uniform2f(GLint location, GLfloat v0, GLfloat v1)
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat v[2];
@@ -144,7 +146,7 @@ _mesa_Uniform2fARB(GLint location, GLfloat v0, GLfloat v1)
 }
 
 void GLAPIENTRY
-_mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
+_mesa_Uniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
 {
    GET_CURRENT_CONTEXT(ctx);
    GLfloat v[3];
@@ -155,7 +157,7 @@ _mesa_Uniform3fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2)
 }
 
 void GLAPIENTRY
-_mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
+_mesa_Uniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
                    GLfloat v3)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -168,14 +170,14 @@ _mesa_Uniform4fARB(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
 }
 
 void GLAPIENTRY
-_mesa_Uniform1iARB(GLint location, GLint v0)
+_mesa_Uniform1i(GLint location, GLint v0)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, 1, &v0, GL_INT);
 }
 
 void GLAPIENTRY
-_mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
+_mesa_Uniform2i(GLint location, GLint v0, GLint v1)
 {
    GET_CURRENT_CONTEXT(ctx);
    GLint v[2];
@@ -185,7 +187,7 @@ _mesa_Uniform2iARB(GLint location, GLint v0, GLint v1)
 }
 
 void GLAPIENTRY
-_mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
+_mesa_Uniform3i(GLint location, GLint v0, GLint v1, GLint v2)
 {
    GET_CURRENT_CONTEXT(ctx);
    GLint v[3];
@@ -196,7 +198,7 @@ _mesa_Uniform3iARB(GLint location, GLint v0, GLint v1, GLint v2)
 }
 
 void GLAPIENTRY
-_mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
+_mesa_Uniform4i(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
 {
    GET_CURRENT_CONTEXT(ctx);
    GLint v[4];
@@ -208,56 +210,56 @@ _mesa_Uniform4iARB(GLint location, GLint v0, GLint v1, GLint v2, GLint v3)
 }
 
 void GLAPIENTRY
-_mesa_Uniform1fvARB(GLint location, GLsizei count, const GLfloat * value)
+_mesa_Uniform1fv(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT);
 }
 
 void GLAPIENTRY
-_mesa_Uniform2fvARB(GLint location, GLsizei count, const GLfloat * value)
+_mesa_Uniform2fv(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC2);
 }
 
 void GLAPIENTRY
-_mesa_Uniform3fvARB(GLint location, GLsizei count, const GLfloat * value)
+_mesa_Uniform3fv(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC3);
 }
 
 void GLAPIENTRY
-_mesa_Uniform4fvARB(GLint location, GLsizei count, const GLfloat * value)
+_mesa_Uniform4fv(GLint location, GLsizei count, const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_FLOAT_VEC4);
 }
 
 void GLAPIENTRY
-_mesa_Uniform1ivARB(GLint location, GLsizei count, const GLint * value)
+_mesa_Uniform1iv(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT);
 }
 
 void GLAPIENTRY
-_mesa_Uniform2ivARB(GLint location, GLsizei count, const GLint * value)
+_mesa_Uniform2iv(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC2);
 }
 
 void GLAPIENTRY
-_mesa_Uniform3ivARB(GLint location, GLsizei count, const GLint * value)
+_mesa_Uniform3iv(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC3);
 }
 
 void GLAPIENTRY
-_mesa_Uniform4ivARB(GLint location, GLsizei count, const GLint * value)
+_mesa_Uniform4iv(GLint location, GLsizei count, const GLint * value)
 {
    GET_CURRENT_CONTEXT(ctx);
    _mesa_uniform(ctx, ctx->Shader.ActiveProgram, location, count, value, GL_INT_VEC4);
@@ -336,7 +338,7 @@ _mesa_Uniform4uiv(GLint location, GLsizei count, const GLuint *value)
 
 
 void GLAPIENTRY
-_mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
+_mesa_UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -345,7 +347,7 @@ _mesa_UniformMatrix2fvARB(GLint location, GLsizei count, GLboolean transpose,
 }
 
 void GLAPIENTRY
-_mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
+_mesa_UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -354,7 +356,7 @@ _mesa_UniformMatrix3fvARB(GLint location, GLsizei count, GLboolean transpose,
 }
 
 void GLAPIENTRY
-_mesa_UniformMatrix4fvARB(GLint location, GLsizei count, GLboolean transpose,
+_mesa_UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose,
                           const GLfloat * value)
 {
    GET_CURRENT_CONTEXT(ctx);
@@ -430,7 +432,7 @@ _mesa_GetnUniformfvARB(GLhandleARB program, GLint location,
 }
 
 void GLAPIENTRY
-_mesa_GetUniformfvARB(GLhandleARB program, GLint location, GLfloat *params)
+_mesa_GetUniformfv(GLhandleARB program, GLint location, GLfloat *params)
 {
    _mesa_GetnUniformfvARB(program, location, INT_MAX, params);
 }
@@ -445,7 +447,7 @@ _mesa_GetnUniformivARB(GLhandleARB program, GLint location,
 }
 
 void GLAPIENTRY
-_mesa_GetUniformivARB(GLhandleARB program, GLint location, GLint *params)
+_mesa_GetUniformiv(GLhandleARB program, GLint location, GLint *params)
 {
    _mesa_GetnUniformivARB(program, location, INT_MAX, params);
 }
@@ -494,9 +496,10 @@ _mesa_GetUniformdv(GLhandleARB program, GLint location, GLdouble *params)
 
 
 GLint GLAPIENTRY
-_mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
+_mesa_GetUniformLocation(GLhandleARB programObj, const GLcharARB *name)
 {
    struct gl_shader_program *shProg;
+   GLuint index, offset;
 
    GET_CURRENT_CONTEXT(ctx);
 
@@ -516,66 +519,323 @@ _mesa_GetUniformLocationARB(GLhandleARB programObj, const GLcharARB *name)
       return -1;
    }
 
-   return _mesa_get_uniform_location(ctx, shProg, name);
+   index = _mesa_get_uniform_location(ctx, shProg, name, &offset);
+   if (index == GL_INVALID_INDEX)
+      return -1;
+
+   /* From the GL_ARB_uniform_buffer_object spec:
+    *
+    *     "The value -1 will be returned if <name> does not correspond to an
+    *      active uniform variable name in <program>, if <name> is associated
+    *      with a named uniform block, or if <name> starts with the reserved
+    *      prefix "gl_"."
+    */
+   if (shProg->UniformStorage[index].block_index != -1)
+      return -1;
+
+   return _mesa_uniform_merge_location_offset(index, offset);
 }
 
+GLuint GLAPIENTRY
+_mesa_GetUniformBlockIndex(GLuint program,
+                          const GLchar *uniformBlockName)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   GLuint i;
+   struct gl_shader_program *shProg;
+
+   if (!ctx->Extensions.ARB_uniform_buffer_object) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "glGetUniformBlockIndex");
+      return GL_INVALID_INDEX;
+   }
+
+   shProg = _mesa_lookup_shader_program_err(ctx, program,
+                                           "glGetUniformBlockIndex");
+   if (!shProg)
+      return GL_INVALID_INDEX;
+
+   for (i = 0; i < shProg->NumUniformBlocks; i++) {
+      if (!strcmp(shProg->UniformBlocks[i].Name, uniformBlockName))
+        return i;
+   }
+
+   return GL_INVALID_INDEX;
+}
+
+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_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;
+        }
+      }
+   }
+}
+
+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);
+   }
+}
 
-/**
- * Plug in shader uniform-related functions into API dispatch table.
- */
 void
-_mesa_init_shader_uniform_dispatch(struct _glapi_table *exec)
-{
-#if FEATURE_GL
-   SET_Uniform1fARB(exec, _mesa_Uniform1fARB);
-   SET_Uniform2fARB(exec, _mesa_Uniform2fARB);
-   SET_Uniform3fARB(exec, _mesa_Uniform3fARB);
-   SET_Uniform4fARB(exec, _mesa_Uniform4fARB);
-   SET_Uniform1iARB(exec, _mesa_Uniform1iARB);
-   SET_Uniform2iARB(exec, _mesa_Uniform2iARB);
-   SET_Uniform3iARB(exec, _mesa_Uniform3iARB);
-   SET_Uniform4iARB(exec, _mesa_Uniform4iARB);
-   SET_Uniform1fvARB(exec, _mesa_Uniform1fvARB);
-   SET_Uniform2fvARB(exec, _mesa_Uniform2fvARB);
-   SET_Uniform3fvARB(exec, _mesa_Uniform3fvARB);
-   SET_Uniform4fvARB(exec, _mesa_Uniform4fvARB);
-   SET_Uniform1ivARB(exec, _mesa_Uniform1ivARB);
-   SET_Uniform2ivARB(exec, _mesa_Uniform2ivARB);
-   SET_Uniform3ivARB(exec, _mesa_Uniform3ivARB);
-   SET_Uniform4ivARB(exec, _mesa_Uniform4ivARB);
-   SET_UniformMatrix2fvARB(exec, _mesa_UniformMatrix2fvARB);
-   SET_UniformMatrix3fvARB(exec, _mesa_UniformMatrix3fvARB);
-   SET_UniformMatrix4fvARB(exec, _mesa_UniformMatrix4fvARB);
-
-   SET_GetActiveUniformARB(exec, _mesa_GetActiveUniformARB);
-   SET_GetUniformLocationARB(exec, _mesa_GetUniformLocationARB);
-   SET_GetUniformfvARB(exec, _mesa_GetUniformfvARB);
-   SET_GetUniformivARB(exec, _mesa_GetUniformivARB);
-
-   /* OpenGL 2.1 */
-   SET_UniformMatrix2x3fv(exec, _mesa_UniformMatrix2x3fv);
-   SET_UniformMatrix3x2fv(exec, _mesa_UniformMatrix3x2fv);
-   SET_UniformMatrix2x4fv(exec, _mesa_UniformMatrix2x4fv);
-   SET_UniformMatrix4x2fv(exec, _mesa_UniformMatrix4x2fv);
-   SET_UniformMatrix3x4fv(exec, _mesa_UniformMatrix3x4fv);
-   SET_UniformMatrix4x3fv(exec, _mesa_UniformMatrix4x3fv);
-
-   /* OpenGL 3.0 */
-   SET_Uniform1uiEXT(exec, _mesa_Uniform1ui);
-   SET_Uniform2uiEXT(exec, _mesa_Uniform2ui);
-   SET_Uniform3uiEXT(exec, _mesa_Uniform3ui);
-   SET_Uniform4uiEXT(exec, _mesa_Uniform4ui);
-   SET_Uniform1uivEXT(exec, _mesa_Uniform1uiv);
-   SET_Uniform2uivEXT(exec, _mesa_Uniform2uiv);
-   SET_Uniform3uivEXT(exec, _mesa_Uniform3uiv);
-   SET_Uniform4uivEXT(exec, _mesa_Uniform4uiv);
-   SET_GetUniformuivEXT(exec, _mesa_GetUniformuiv);
-
-   /* GL_ARB_robustness */
-   SET_GetnUniformfvARB(exec, _mesa_GetnUniformfvARB);
-   SET_GetnUniformivARB(exec, _mesa_GetnUniformivARB);
-   SET_GetnUniformuivARB(exec, _mesa_GetnUniformuivARB);
-   SET_GetnUniformdvARB(exec, _mesa_GetnUniformdvARB); /* GL 4.0 */
-
-#endif /* FEATURE_GL */
+_mesa_get_uniform_name(const struct gl_uniform_storage *uni,
+                       GLsizei maxLength, GLsizei *length,
+                       GLchar *nameOut)
+{
+   GLsizei localLength;
+
+   if (length == NULL)
+      length = &localLength;
+
+   _mesa_copy_string(nameOut, maxLength, length, uni->name);
+
+   /* Page 61 (page 73 of the PDF) in section 2.11 of the OpenGL ES 3.0
+    * spec says:
+    *
+    *     "If the active uniform is an array, the uniform name returned in
+    *     name will always be the name of the uniform array appended with
+    *     "[0]"."
+    *
+    * The same text also appears in the OpenGL 4.2 spec.  It does not,
+    * however, appear in any previous spec.  Previous specifications are
+    * ambiguous in this regard.  However, either name can later be passed
+    * to glGetUniformLocation (and related APIs), so there shouldn't be any
+    * harm in always appending "[0]" to uniform array names.
+    */
+   if (uni->array_elements != 0) {
+      unsigned i;
+
+      /* The comparison is strange because *length does *NOT* include the
+       * terminating NUL, but maxLength does.
+       */
+      for (i = 0; i < 3 && (*length + i + 1) < maxLength; i++)
+         nameOut[*length + i] = "[0]"[i];
+
+      nameOut[*length + i] = '\0';
+      *length += i;
+   }
 }