mesa: Rename _mesa_lookup_enum_by_nr() to _mesa_enum_to_string().
[mesa.git] / src / mesa / main / program_resource.c
index a60b2e4e658b8e194dfb471cfd886b0e54b66713..e77bb03e9a17cd6216980cb7cf2aa74a8b6b5708 100644 (file)
@@ -81,7 +81,7 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
    /* Validate interface. */
    if (!supported_interface_enum(programInterface)) {
       _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
-                  _mesa_lookup_enum_by_nr(programInterface));
+                  _mesa_enum_to_string(programInterface));
       return;
    }
 
@@ -96,8 +96,8 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
       if (programInterface == GL_ATOMIC_COUNTER_BUFFER) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "glGetProgramInterfaceiv(%s pname %s)",
-                     _mesa_lookup_enum_by_nr(programInterface),
-                     _mesa_lookup_enum_by_nr(pname));
+                     _mesa_enum_to_string(programInterface),
+                     _mesa_enum_to_string(pname));
          return;
       }
       /* Name length consists of base name, 3 additional chars '[0]' if
@@ -138,15 +138,15 @@ _mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface,
       default:
         _mesa_error(ctx, GL_INVALID_OPERATION,
                     "glGetProgramInterfaceiv(%s pname %s)",
-                    _mesa_lookup_enum_by_nr(programInterface),
-                    _mesa_lookup_enum_by_nr(pname));
+                    _mesa_enum_to_string(programInterface),
+                    _mesa_enum_to_string(pname));
       };
       break;
    case GL_MAX_NUM_COMPATIBLE_SUBROUTINES:
    default:
       _mesa_error(ctx, GL_INVALID_OPERATION,
                   "glGetProgramInterfaceiv(pname %s)",
-                  _mesa_lookup_enum_by_nr(pname));
+                  _mesa_enum_to_string(pname));
    }
 }
 
@@ -220,12 +220,12 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
    case GL_PROGRAM_INPUT:
    case GL_PROGRAM_OUTPUT:
    case GL_UNIFORM:
-   case GL_UNIFORM_BLOCK:
    case GL_TRANSFORM_FEEDBACK_VARYING:
-      /* Validate name syntax for arrays. */
+      /* Validate name syntax for array variables */
       if (!valid_program_resource_index_name(name))
          return GL_INVALID_INDEX;
-
+      /* fall-through */
+   case GL_UNIFORM_BLOCK:
       res = _mesa_program_resource_find_name(shProg, programInterface, name);
       if (!res)
          return GL_INVALID_INDEX;
@@ -234,7 +234,7 @@ _mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
    case GL_ATOMIC_COUNTER_BUFFER:
    default:
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
-                  _mesa_lookup_enum_by_nr(programInterface));
+                  _mesa_enum_to_string(programInterface));
    }
 
    return GL_INVALID_INDEX;
@@ -262,7 +262,7 @@ _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
    if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
        !supported_interface_enum(programInterface)) {
       _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
-                  _mesa_lookup_enum_by_nr(programInterface));
+                  _mesa_enum_to_string(programInterface));
       return;
    }
 
@@ -276,18 +276,142 @@ _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
                            const GLenum *props, GLsizei bufSize,
                            GLsizei *length, GLint *params)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
+
+   if (!shProg || !params)
+      return;
+
+   /* The error INVALID_VALUE is generated if <propCount> is zero.
+    * Note that we check < 0 here because it makes sense to bail early.
+    */
+   if (propCount <= 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE,
+                  "glGetProgramResourceiv(propCount <= 0)");
+      return;
+   }
+
+   /* No need to write any properties, user requested none. */
+   if (bufSize == 0)
+      return;
+
+   _mesa_get_program_resourceiv(shProg, programInterface, index,
+                                propCount, props, bufSize, length, params);
+}
+
+/**
+ * Function verifies syntax of given name for GetProgramResourceLocation
+ * and GetProgramResourceLocationIndex for the following cases:
+ *
+ * "array element portion of a string passed to GetProgramResourceLocation
+ * or GetProgramResourceLocationIndex must not have, a "+" sign, extra
+ * leading zeroes, or whitespace".
+ *
+ * Check is written to be compatible with GL_ARB_array_of_arrays.
+ */
+static bool
+invalid_array_element_syntax(const GLchar *name)
+{
+   char *first = strchr(name, '[');
+   char *last = strrchr(name, '[');
+
+   if (!first)
+      return false;
+
+   /* No '+' or ' ' allowed anywhere. */
+   if (strchr(first, '+') || strchr(first, ' '))
+      return true;
+
+   /* Check that last array index is 0. */
+   if (last[1] == '0' && last[2] != ']')
+      return true;
+
+   return false;
+}
+
+static struct gl_shader_program *
+lookup_linked_program(GLuint program, const char *caller)
+{
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *prog =
+      _mesa_lookup_shader_program_err(ctx, program, caller);
+
+   if (!prog)
+      return NULL;
+
+   if (prog->LinkStatus == GL_FALSE) {
+      _mesa_error(ctx, GL_INVALID_OPERATION, "%s(program not linked)",
+                  caller);
+      return NULL;
+   }
+   return prog;
 }
 
 GLint GLAPIENTRY
 _mesa_GetProgramResourceLocation(GLuint program, GLenum programInterface,
                                  const GLchar *name)
 {
-   return -1;
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      lookup_linked_program(program, "glGetProgramResourceLocation");
+
+   if (!shProg || !name || invalid_array_element_syntax(name))
+      return -1;
+
+   /* Validate programInterface. */
+   switch (programInterface) {
+   case GL_UNIFORM:
+   case GL_PROGRAM_INPUT:
+   case GL_PROGRAM_OUTPUT:
+      break;
+
+   /* For reference valid cases requiring additional extension support:
+    * GL_ARB_shader_subroutine
+    * GL_ARB_tessellation_shader
+    * GL_ARB_compute_shader
+    */
+   case GL_VERTEX_SUBROUTINE_UNIFORM:
+   case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+   case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+   case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+   case GL_FRAGMENT_SUBROUTINE_UNIFORM:
+   case GL_COMPUTE_SUBROUTINE_UNIFORM:
+
+   default:
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
+                  _mesa_enum_to_string(programInterface), name);
+   }
+
+   return _mesa_program_resource_location(shProg, programInterface, name);
 }
 
+/**
+ * Returns output index for dual source blending.
+ */
 GLint GLAPIENTRY
 _mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface,
                                       const GLchar *name)
 {
-   return -1;
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      lookup_linked_program(program, "glGetProgramResourceLocationIndex");
+
+   if (!shProg || !name || invalid_array_element_syntax(name))
+      return -1;
+
+   /* From the GL_ARB_program_interface_query spec:
+    *
+    * "For GetProgramResourceLocationIndex, <programInterface> must be
+    * PROGRAM_OUTPUT."
+    */
+   if (programInterface != GL_PROGRAM_OUTPUT) {
+      _mesa_error(ctx, GL_INVALID_ENUM,
+                  "glGetProgramResourceLocationIndex(%s)",
+                  _mesa_enum_to_string(programInterface));
+      return -1;
+   }
+
+   return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT,
+                                                name);
 }