#include "main/mtypes.h"
#include "main/shaderapi.h"
#include "main/shaderobj.h"
+#include "main/context.h"
#include "program_resource.h"
-
+#include "ir_uniform.h"
static bool
-supported_interface_enum(GLenum iface)
+supported_interface_enum(struct gl_context *ctx, GLenum iface)
{
switch (iface) {
case GL_UNIFORM:
case GL_ATOMIC_COUNTER_BUFFER:
return true;
case GL_VERTEX_SUBROUTINE:
- case GL_TESS_CONTROL_SUBROUTINE:
- case GL_TESS_EVALUATION_SUBROUTINE:
- case GL_GEOMETRY_SUBROUTINE:
case GL_FRAGMENT_SUBROUTINE:
- case GL_COMPUTE_SUBROUTINE:
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:
+ return _mesa_has_shader_subroutine(ctx);
+ case GL_GEOMETRY_SUBROUTINE:
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ return _mesa_has_geometry_shaders(ctx) && _mesa_has_shader_subroutine(ctx);
+ case GL_COMPUTE_SUBROUTINE:
case GL_COMPUTE_SUBROUTINE_UNIFORM:
+ return _mesa_has_compute_shaders(ctx) && _mesa_has_shader_subroutine(ctx);
+ case GL_TESS_CONTROL_SUBROUTINE:
+ case GL_TESS_EVALUATION_SUBROUTINE:
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+ return _mesa_has_tessellation(ctx) && _mesa_has_shader_subroutine(ctx);
case GL_BUFFER_VARIABLE:
case GL_SHADER_STORAGE_BLOCK:
default:
}
/* Validate interface. */
- if (!supported_interface_enum(programInterface)) {
+ if (!supported_interface_enum(ctx, programInterface)) {
_mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)",
- _mesa_lookup_enum_by_nr(programInterface));
+ _mesa_enum_to_string(programInterface));
return;
}
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
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:
+ switch (programInterface) {
+ case GL_VERTEX_SUBROUTINE_UNIFORM:
+ case GL_FRAGMENT_SUBROUTINE_UNIFORM:
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ case GL_COMPUTE_SUBROUTINE_UNIFORM:
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM: {
+ for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) {
+ if (shProg->ProgramResourceList[i].Type == programInterface) {
+ struct gl_uniform_storage *uni =
+ (struct gl_uniform_storage *)
+ shProg->ProgramResourceList[i].Data;
+ *params = MAX2(*params, uni->num_compatible_subroutines);
+ }
+ }
+ break;
+ }
+
+ default:
+ _mesa_error(ctx, GL_INVALID_OPERATION,
+ "glGetProgramInterfaceiv(%s pname %s)",
+ _mesa_enum_to_string(programInterface),
+ _mesa_enum_to_string(pname));
+ }
+ break;
default:
_mesa_error(ctx, GL_INVALID_OPERATION,
"glGetProgramInterfaceiv(pname %s)",
- _mesa_lookup_enum_by_nr(pname));
+ _mesa_enum_to_string(pname));
}
}
return false;
}
-/**
- * Checks if given name index is legal for GetProgramResourceIndex,
- * check is written to be compatible with GL_ARB_array_of_arrays.
- */
-static bool
-valid_program_resource_index_name(const GLchar *name)
-{
- const char *array = strstr(name, "[");
- const char *close = strrchr(name, ']');
-
- /* Not array, no need for the check. */
- if (!array)
- return true;
-
- /* Last array index has to be zero. */
- if (!close || *--close != '0')
- return false;
-
- return true;
-}
-
GLuint GLAPIENTRY
_mesa_GetProgramResourceIndex(GLuint program, GLenum programInterface,
const GLchar *name)
{
GET_CURRENT_CONTEXT(ctx);
+ unsigned array_index = 0;
struct gl_program_resource *res;
struct gl_shader_program *shProg =
_mesa_lookup_shader_program_err(ctx, program,
if (!shProg || !name)
return GL_INVALID_INDEX;
+ if (!supported_interface_enum(ctx, programInterface)) {
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceIndex(%s)",
+ _mesa_enum_to_string(programInterface));
+ return GL_INVALID_INDEX;
+ }
/*
* For the interface TRANSFORM_FEEDBACK_VARYING, the value INVALID_INDEX
* should be returned when querying the index assigned to the special names
return GL_INVALID_INDEX;
switch (programInterface) {
+ case GL_TESS_CONTROL_SUBROUTINE:
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+ case GL_COMPUTE_SUBROUTINE:
+ case GL_COMPUTE_SUBROUTINE_UNIFORM:
+ case GL_GEOMETRY_SUBROUTINE:
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ case GL_VERTEX_SUBROUTINE:
+ case GL_FRAGMENT_SUBROUTINE:
+ case GL_VERTEX_SUBROUTINE_UNIFORM:
+ case GL_FRAGMENT_SUBROUTINE_UNIFORM:
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. */
- if (!valid_program_resource_index_name(name))
- return GL_INVALID_INDEX;
-
- res = _mesa_program_resource_find_name(shProg, programInterface, name);
- if (!res)
+ case GL_UNIFORM_BLOCK:
+ res = _mesa_program_resource_find_name(shProg, programInterface, name,
+ &array_index);
+ if (!res || array_index > 0)
return GL_INVALID_INDEX;
return _mesa_program_resource_index(shProg, res);
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;
_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)) {
+ !supported_interface_enum(ctx, programInterface)) {
_mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceName(%s)",
- _mesa_lookup_enum_by_nr(programInterface));
+ _mesa_enum_to_string(programInterface));
return;
}
const GLenum *props, GLsizei bufSize,
GLsizei *length, GLint *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, '[');
+ GET_CURRENT_CONTEXT(ctx);
+ struct gl_shader_program *shProg =
+ _mesa_lookup_shader_program_err(ctx, program, "glGetProgramResourceiv");
- if (!first)
- return false;
+ if (!shProg || !params)
+ return;
- /* No '+' or ' ' allowed anywhere. */
- if (strchr(first, '+') || strchr(first, ' '))
- return true;
+ /* 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;
+ }
- /* Check that last array index is 0. */
- if (last[1] == '0' && last[2] != ']')
- return true;
+ /* No need to write any properties, user requested none. */
+ if (bufSize == 0)
+ return;
- return false;
+ _mesa_get_program_resourceiv(shProg, programInterface, index,
+ propCount, props, bufSize, length, params);
}
static struct gl_shader_program *
struct gl_shader_program *shProg =
lookup_linked_program(program, "glGetProgramResourceLocation");
- if (!shProg || !name || invalid_array_element_syntax(name))
+ if (!shProg || !name)
return -1;
/* Validate programInterface. */
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:
+ if (!_mesa_has_shader_subroutine(ctx))
+ goto fail;
+ break;
+ case GL_GEOMETRY_SUBROUTINE_UNIFORM:
+ if (!_mesa_has_geometry_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
+ goto fail;
+ break;
case GL_COMPUTE_SUBROUTINE_UNIFORM:
-
+ if (!_mesa_has_compute_shaders(ctx) || !_mesa_has_shader_subroutine(ctx))
+ goto fail;
+ break;
+ case GL_TESS_CONTROL_SUBROUTINE_UNIFORM:
+ case GL_TESS_EVALUATION_SUBROUTINE_UNIFORM:
+ if (!_mesa_has_tessellation(ctx) || !_mesa_has_shader_subroutine(ctx))
+ goto fail;
+ break;
default:
- _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
- _mesa_lookup_enum_by_nr(programInterface), name);
+ goto fail;
}
return _mesa_program_resource_location(shProg, programInterface, name);
+fail:
+ _mesa_error(ctx, GL_INVALID_ENUM, "glGetProgramResourceLocation(%s %s)",
+ _mesa_enum_to_string(programInterface), name);
+ return -1;
}
+/**
+ * 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)
+ 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);
}