mesa: glGetProgramResourceLocation

Patch adds required helper functions to shaderapi.h and
the actual implementation.

corresponding Piglit test:
   arb_program_interface_query-resource-location

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

   GetAttribLocation
   GetUniformLocation
   GetFragDataLocation

v2: code cleanup, changes to array element
    syntax checking (Ilia Mirkin)

Signed-off-by: Tapani Pälli <tapani.palli@intel.com>
Reviewed-by: Martin Peres <martin.peres@linux.intel.com>
This commit is contained in:
Tapani Pälli 2015-03-12 13:45:22 +02:00
parent 2a5a0d19d6
commit e0e4d77f01
3 changed files with 151 additions and 1 deletions

View file

@ -278,11 +278,90 @@ _mesa_GetProgramResourceiv(GLuint program, GLenum programInterface,
{
}
/**
* 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_lookup_enum_by_nr(programInterface), name);
}
return _mesa_program_resource_location(shProg, programInterface, name);
}
GLint GLAPIENTRY

View file

@ -754,3 +754,70 @@ _mesa_get_program_resource_name(struct gl_shader_program *shProg,
}
return true;
}
static GLint
program_resource_location(struct gl_shader_program *shProg,
struct gl_program_resource *res, const char *name)
{
unsigned index, offset;
int array_index = -1;
if (res->Type == GL_PROGRAM_INPUT || res->Type == GL_PROGRAM_OUTPUT) {
array_index = array_index_of_resource(res, name);
if (array_index < 0)
return -1;
}
/* VERT_ATTRIB_GENERIC0 and FRAG_RESULT_DATA0 are decremented as these
* offsets are used internally to differentiate between built-in attributes
* and user-defined attributes.
*/
switch (res->Type) {
case GL_PROGRAM_INPUT:
return RESOURCE_VAR(res)->data.location + array_index - VERT_ATTRIB_GENERIC0;
case GL_PROGRAM_OUTPUT:
return RESOURCE_VAR(res)->data.location + array_index - FRAG_RESULT_DATA0;
case GL_UNIFORM:
index = _mesa_get_uniform_location(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 (RESOURCE_UNI(res)->block_index != -1 ||
RESOURCE_UNI(res)->atomic_buffer_index != -1)
return -1;
/* location in remap table + array element offset */
return RESOURCE_UNI(res)->remap_location + offset;
default:
return -1;
}
}
/**
* Function implements following location queries:
* glGetAttribLocation
* glGetFragDataLocation
* glGetUniformLocation
*/
GLint
_mesa_program_resource_location(struct gl_shader_program *shProg,
GLenum interface, const char *name)
{
struct gl_program_resource *res =
_mesa_program_resource_find_name(shProg, interface, name);
/* Resource not found. */
if (!res)
return -1;
return program_resource_location(shProg, res, name);
}

View file

@ -244,6 +244,10 @@ _mesa_get_program_resource_name(struct gl_shader_program *shProg,
GLsizei bufSize, GLsizei *length,
GLchar *name, const char *caller);
extern GLint
_mesa_program_resource_location(struct gl_shader_program *shProg,
GLenum interface, const char *name);
#ifdef __cplusplus
}
#endif