summaryrefslogtreecommitdiffstats
path: root/src/mesa
diff options
context:
space:
mode:
Diffstat (limited to 'src/mesa')
-rw-r--r--src/mesa/main/program_resource.c23
-rw-r--r--src/mesa/main/shader_query.cpp106
-rw-r--r--src/mesa/main/shaderapi.h10
3 files changed, 139 insertions, 0 deletions
diff --git a/src/mesa/main/program_resource.c b/src/mesa/main/program_resource.c
index 7a2732503a9..a60b2e4e658 100644
--- a/src/mesa/main/program_resource.c
+++ b/src/mesa/main/program_resource.c
@@ -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
diff --git a/src/mesa/main/shader_query.cpp b/src/mesa/main/shader_query.cpp
index 61eec68683f..ab61be97a09 100644
--- a/src/mesa/main/shader_query.cpp
+++ b/src/mesa/main/shader_query.cpp
@@ -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;
+}
diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h
index d80252b460a..7a7e3e9e731 100644
--- a/src/mesa/main/shaderapi.h
+++ b/src/mesa/main/shaderapi.h
@@ -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