mesa: glGetProgramResourceName
authorTapani Pälli <tapani.palli@intel.com>
Tue, 10 Mar 2015 08:33:20 +0000 (10:33 +0200)
committerTapani Pälli <tapani.palli@intel.com>
Thu, 16 Apr 2015 04:55:56 +0000 (07:55 +0300)
Patch adds required helper functions to shaderapi.h and
the actual implementation.

Name generation copied from '_mesa_get_uniform_name' which can
be removed later by refactoring functions to use resource list.

The added functionality can be tested by tests for following
functions that are refactored by later patches:

   GetActiveUniformName
   GetActiveUniformBlockName

v2: no index for geometry shader inputs (Ilia Mirkin)
    add bufSize < 0 check and error out
    validate enum

corresponding Piglit test:
   arb_program_interface_query-getprogramresourcename

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Martin Peres <martin.peres@linux.intel.org>
src/mesa/main/program_resource.c
src/mesa/main/shader_query.cpp
src/mesa/main/shaderapi.h

index 7a2732503a98e720e962e601a53445896ad458b7..a60b2e4e658b8e194dfb471cfd886b0e54b66713 100644 (file)
@@ -245,6 +245,29 @@ _mesa_GetProgramResourceName(GLuint program, GLenum programInterface,
                              GLuint index, GLsizei bufSize, GLsizei *length,
                              GLchar *name)
 {
+   GET_CURRENT_CONTEXT(ctx);
+   struct gl_shader_program *shProg =
+      _mesa_lookup_shader_program_err(ctx, program,
+                                      "glGetProgramResourceName");
+
+   /* Set user friendly return values in case of errors. */
+   if (name)
+      *name = '\0';
+   if (length)
+      *length = 0;
+
+   if (!shProg || !name)
+      return;
+
+   if (programInterface == GL_ATOMIC_COUNTER_BUFFER ||
+       !supported_interface_enum(programInterface)) {
+      _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
+                  _mesa_lookup_enum_by_nr(programInterface));
+      return;
+   }
+
+   _mesa_get_program_resource_name(shProg, programInterface, index, bufSize,
+                                   length, name, "glGetProgramResourceName");
 }
 
 void GLAPIENTRY
index 61eec68683f97671aafa87ffa7a523ea22cb4f2a..ab61be97a09e847adc1afa8f60ae8d6c494f7107 100644 (file)
@@ -648,3 +648,109 @@ _mesa_program_resource_index(struct gl_shader_program *shProg,
       return calc_resource_index(shProg, res);
    }
 }
+
+/* Find a program resource with specific index in given interface.
+ */
+struct gl_program_resource *
+_mesa_program_resource_find_index(struct gl_shader_program *shProg,
+                                  GLenum interface, GLuint index)
+{
+   struct gl_program_resource *res = shProg->ProgramResourceList;
+   int idx = -1;
+
+   for (unsigned i = 0; i < shProg->NumProgramResourceList; i++, res++) {
+      if (res->Type != interface)
+         continue;
+
+      switch (res->Type) {
+      case GL_UNIFORM_BLOCK:
+      case GL_ATOMIC_COUNTER_BUFFER:
+         if (_mesa_program_resource_index(shProg, res) == index)
+            return res;
+
+      case GL_TRANSFORM_FEEDBACK_VARYING:
+      case GL_PROGRAM_INPUT:
+      case GL_PROGRAM_OUTPUT:
+      case GL_UNIFORM:
+         if (++idx == (int) index)
+            return res;
+         break;
+      default:
+         assert(!"not implemented for given interface");
+      }
+   }
+   return NULL;
+}
+
+/* Get full name of a program resource.
+ */
+bool
+_mesa_get_program_resource_name(struct gl_shader_program *shProg,
+                                GLenum interface, GLuint index,
+                                GLsizei bufSize, GLsizei *length,
+                                GLchar *name, const char *caller)
+{
+   GET_CURRENT_CONTEXT(ctx);
+
+   /* Find resource with given interface and index. */
+   struct gl_program_resource *res =
+      _mesa_program_resource_find_index(shProg, interface, index);
+
+   /* The error INVALID_VALUE is generated if <index> is greater than
+   * or equal to the number of entries in the active resource list for
+   * <programInterface>.
+   */
+   if (!res) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(index %u)", caller, index);
+      return false;
+   }
+
+   if (bufSize < 0) {
+      _mesa_error(ctx, GL_INVALID_VALUE, "%s(bufSize %d)", caller, bufSize);
+      return false;
+   }
+
+   GLsizei localLength;
+
+   if (length == NULL)
+      length = &localLength;
+
+   _mesa_copy_string(name, bufSize, length, _mesa_program_resource_name(res));
+
+   /* 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.
+    *
+    * Geometry shader stage has different naming convention where the 'normal'
+    * condition is an array, therefore for variables referenced in geometry
+    * stage we do not add '[0]'.
+    *
+    * Note, that TCS outputs and TES inputs should not have index appended
+    * either.
+    */
+   bool add_index = !(((interface == GL_PROGRAM_INPUT) &&
+                       res->StageReferences & (1 << MESA_SHADER_GEOMETRY)));
+
+   if (add_index && _mesa_program_resource_array_size(res)) {
+      int i;
+
+      /* The comparison is strange because *length does *NOT* include the
+       * terminating NUL, but maxLength does.
+       */
+      for (i = 0; i < 3 && (*length + i + 1) < bufSize; i++)
+         name[*length + i] = "[0]"[i];
+
+      name[*length + i] = '\0';
+      *length += i;
+   }
+   return true;
+}
index d80252b460ac4878aa4e46bb929e52b666faaa7c..7a7e3e9e731a3e6f2fba02cbaac11a47602f53e9 100644 (file)
@@ -234,6 +234,16 @@ extern struct gl_program_resource *
 _mesa_program_resource_find_name(struct gl_shader_program *shProg,
                                  GLenum interface, const char *name);
 
+extern struct gl_program_resource *
+_mesa_program_resource_find_index(struct gl_shader_program *shProg,
+                                  GLenum interface, GLuint index);
+
+extern bool
+_mesa_get_program_resource_name(struct gl_shader_program *shProg,
+                                GLenum interface, GLuint index,
+                                GLsizei bufSize, GLsizei *length,
+                                GLchar *name, const char *caller);
+
 #ifdef __cplusplus
 }
 #endif