From 4ba9be2882d9f1567809edb0a31fcdf11320d41f Mon Sep 17 00:00:00 2001 From: marha Date: Mon, 20 Apr 2015 21:25:25 +0200 Subject: randrproto xkeyboard-config fontconfig libX11 libXdmcp libXmu pixman xkbcomp xserver mesa git update 20 Apr 2015 xserver commit b1029716e41e252f149b82124a149da180607c96 xkeyboard-config commit 7d00bcc2d9c3944bbdfcbe472ee3299729dc7687 libX11 commit 748d47e69f5c12d8557d56a8a8ec166588da7b93 libXdmcp commit b10f382e3aa2e86cd5a2bc27d6758da55f0ab1f6 xkbcomp commit 1ae525b3d236b59e6437b2b5433d460e18370973 pixman commit 58e21d3e45c5227c2ca9ac00cf044f22a7975180 randrproto commit 98da0d6e48b7d124d6788ea568e9f9e3dc204322 libXmu commit 4459e6940fe3fdf26a8d5d4c71989498bc400a62 fontconfig commit 07be485a0a84995ce69bf60e3b1bb22cb35f6b0e mesa commit c1485f4b7d044724b3dbc1011f3c3a8a53132010 --- mesalib/src/mesa/main/program_resource.c | 417 +++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100644 mesalib/src/mesa/main/program_resource.c (limited to 'mesalib/src/mesa/main/program_resource.c') diff --git a/mesalib/src/mesa/main/program_resource.c b/mesalib/src/mesa/main/program_resource.c new file mode 100644 index 000000000..b15a13210 --- /dev/null +++ b/mesalib/src/mesa/main/program_resource.c @@ -0,0 +1,417 @@ +/* + * Mesa 3-D graphics library + * + * Copyright (C) 2015 Intel Corporation. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + * OTHER DEALINGS IN THE SOFTWARE. + * + */ + +#include "main/enums.h" +#include "main/macros.h" +#include "main/mtypes.h" +#include "main/shaderapi.h" +#include "main/shaderobj.h" +#include "program_resource.h" + +static bool +supported_interface_enum(GLenum iface) +{ + switch (iface) { + case GL_UNIFORM: + case GL_UNIFORM_BLOCK: + case GL_PROGRAM_INPUT: + case GL_PROGRAM_OUTPUT: + case GL_TRANSFORM_FEEDBACK_VARYING: + 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: + case GL_COMPUTE_SUBROUTINE_UNIFORM: + case GL_BUFFER_VARIABLE: + case GL_SHADER_STORAGE_BLOCK: + default: + return false; + } +} + +void GLAPIENTRY +_mesa_GetProgramInterfaceiv(GLuint program, GLenum programInterface, + GLenum pname, GLint *params) +{ + GET_CURRENT_CONTEXT(ctx); + unsigned i; + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramInterfaceiv"); + if (!shProg) + return; + + if (!params) { + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(params NULL)"); + return; + } + + /* Validate interface. */ + if (!supported_interface_enum(programInterface)) { + _mesa_error(ctx, GL_INVALID_OPERATION, "glGetProgramInterfaceiv(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return; + } + + /* Validate pname against interface. */ + switch(pname) { + case GL_ACTIVE_RESOURCES: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) + if (shProg->ProgramResourceList[i].Type == programInterface) + (*params)++; + break; + case GL_MAX_NAME_LENGTH: + 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)); + return; + } + /* Name length consists of base name, 3 additional chars '[0]' if + * resource is an array and finally 1 char for string terminator. + */ + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type != programInterface) + continue; + const char *name = + _mesa_program_resource_name(&shProg->ProgramResourceList[i]); + unsigned array_size = + _mesa_program_resource_array_size(&shProg->ProgramResourceList[i]); + *params = MAX2(*params, strlen(name) + (array_size ? 3 : 0) + 1); + } + break; + case GL_MAX_NUM_ACTIVE_VARIABLES: + switch (programInterface) { + case GL_UNIFORM_BLOCK: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_uniform_block *block = + (struct gl_uniform_block *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, block->NumUniforms); + } + } + break; + case GL_ATOMIC_COUNTER_BUFFER: + for (i = 0, *params = 0; i < shProg->NumProgramResourceList; i++) { + if (shProg->ProgramResourceList[i].Type == programInterface) { + struct gl_active_atomic_buffer *buffer = + (struct gl_active_atomic_buffer *) + shProg->ProgramResourceList[i].Data; + *params = MAX2(*params, buffer->NumUniforms); + } + } + break; + default: + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(%s pname %s)", + _mesa_lookup_enum_by_nr(programInterface), + _mesa_lookup_enum_by_nr(pname)); + }; + break; + case GL_MAX_NUM_COMPATIBLE_SUBROUTINES: + default: + _mesa_error(ctx, GL_INVALID_OPERATION, + "glGetProgramInterfaceiv(pname %s)", + _mesa_lookup_enum_by_nr(pname)); + } +} + +static bool +is_xfb_marker(const char *str) +{ + static const char *markers[] = { + "gl_NextBuffer", + "gl_SkipComponents1", + "gl_SkipComponents2", + "gl_SkipComponents3", + "gl_SkipComponents4", + NULL + }; + const char **m = markers; + + if (strncmp(str, "gl_", 3) != 0) + return false; + + for (; *m; m++) + if (strcmp(*m, str) == 0) + return true; + + 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); + struct gl_program_resource *res; + struct gl_shader_program *shProg = + _mesa_lookup_shader_program_err(ctx, program, + "glGetProgramResourceIndex"); + if (!shProg || !name) + 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 + * "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2", + * "gl_SkipComponents3", and "gl_SkipComponents4". + */ + if (programInterface == GL_TRANSFORM_FEEDBACK_VARYING && + is_xfb_marker(name)) + return GL_INVALID_INDEX; + + switch (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. */ + if (!valid_program_resource_index_name(name)) + return GL_INVALID_INDEX; + + res = _mesa_program_resource_find_name(shProg, programInterface, name); + if (!res) + 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)); + } + + return GL_INVALID_INDEX; +} + +void GLAPIENTRY +_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 +_mesa_GetProgramResourceiv(GLuint program, GLenum programInterface, + GLuint index, GLsizei propCount, + 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 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) +{ + 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); +} + +/** + * Returns output index for dual source blending. + */ +GLint GLAPIENTRY +_mesa_GetProgramResourceLocationIndex(GLuint program, GLenum programInterface, + const GLchar *name) +{ + 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, must be + * PROGRAM_OUTPUT." + */ + if (programInterface != GL_PROGRAM_OUTPUT) { + _mesa_error(ctx, GL_INVALID_ENUM, + "glGetProgramResourceLocationIndex(%s)", + _mesa_lookup_enum_by_nr(programInterface)); + return -1; + } + + return _mesa_program_resource_location_index(shProg, GL_PROGRAM_OUTPUT, + name); +} -- cgit v1.2.3