/* * Copyright © 2015 Intel Corporation * * 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 (including the next * paragraph) 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. */ /** * \file getprograminterfaceiv.c * * Tests the error cases of the GetProgramInterfaceiv interface. * * From the GL_ARB_program_interface_query spec: * "The command * * void GetProgramInterfaceiv(uint program, enum programInterface, * enum pname, int *params); * * queries a property of the interface in program * , returning its value in . The property to return is * specified by . * * If is ACTIVE_RESOURCES, the value returned is the number of * resources in the active resource list for . If the * list of active resources for is empty, zero is * returned. * * If is MAX_NAME_LENGTH, the value returned is the length of the * longest active name string for an active resource in . * This length includes an extra character for the null terminator. If * the list of active resources for is empty, zero is * returned. The error INVALID_OPERATION is generated if * is ATOMIC_COUNTER_BUFFER, since active atomic counter * buffer resources are not assigned name strings. * * If is MAX_NUM_ACTIVE_VARIABLES, the value returned is the number * of active variables belonging to the interface block or atomic counter * buffer resource in with the most active variables. * If the list of active resources for is empty, zero is * returned. The error INVALID_OPERATION is generated if * is not UNIFORM_BLOCK, ATOMIC_COUNTER_BUFFER, or * SHADER_STORAGE_BLOCK. * * If is MAX_NUM_COMPATIBLE_SUBROUTINES, the value returned is the * number of compatible subroutines belonging to the active subroutine * uniform in with the most compatible subroutines. If * the list of active resources for is empty, zero is * returned. The error INVALID_OPERATION is generated unless * is VERTEX_SUBROUTINE_UNIFORM, * TESS_CONTROL_SUBROUTINE_UNIFORM, TESS_EVALUATION_SUBROUTINE_UNIFORM, * GEOMETRY_SUBROUTINE_UNIFORM, FRAGMENT_SUBROUTINE_UNIFORM, or * COMPUTE_SUBROUTINE_UNIFORM. * * [...] * * An INVALID_VALUE error is generated by GetProgramInterfaceiv, * GetProgramResourceIndex, GetProgramResourceName, GetProgramResourceiv, * GetProgramResourceLocation, and GetProgramResourceLocationIndex if * is not the name of either a shader or program object. * * An INVALID_OPERATION error is generated by GetProgramInterfaceiv, * GetProgramResourceIndex, GetProgramResourceName, GetProgramResourceiv, * GetProgramResourceLocation, and GetProgramResourceLocationIndex if * is the name of a shader object. * * INVALID_OPERATION is generated by GetProgramInterfaceiv if the parameter * is not supported for the interface ." */ #include "piglit-util-gl.h" #include "common.h" PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_core_version = 32; config.khr_no_error_support = PIGLIT_HAS_ERRORS; PIGLIT_GL_TEST_CONFIG_END struct subtest_t { GLenum programInterface; GLenum pname; GLenum expected_error; }; static const struct subtest_t programInterface_subtests[] = { { GL_TRUE, GL_MAX_NAME_LENGTH, GL_INVALID_OPERATION }, { GL_UNIFORM, GL_TRUE, GL_INVALID_OPERATION }, { GL_ATOMIC_COUNTER_BUFFER, GL_MAX_NAME_LENGTH, GL_INVALID_OPERATION }, { GL_UNIFORM, GL_MAX_NUM_ACTIVE_VARIABLES, GL_INVALID_OPERATION }, { GL_PROGRAM_OUTPUT, GL_MAX_NUM_COMPATIBLE_SUBROUTINES, GL_INVALID_OPERATION }, }; static bool check_extensions(const struct subtest_t st) { if (st.programInterface == GL_ATOMIC_COUNTER_BUFFER && !piglit_is_extension_supported("GL_ARB_shader_atomic_counters")) { return false; } return true; } static void run_subtest(const struct subtest_t st, GLuint prog, bool *pass) { enum piglit_result result; bool local_pass = true; int value; const char *programInterface_str = piglit_get_gl_enum_name(st.programInterface); const char *pname_str = piglit_get_gl_enum_name(st.pname); if (!check_extensions(st)) { result = PIGLIT_SKIP; goto report_result; } glGetProgramInterfaceiv(prog, st.programInterface, st.pname, &value); if (!piglit_check_gl_error(st.expected_error)) { printf(" Call was glGetProgramInterfaceiv(prog, %s, " "%s, ...)\n", programInterface_str, pname_str); local_pass = false; } *pass = *pass && local_pass; result = local_pass ? PIGLIT_PASS : PIGLIT_FAIL; report_result: piglit_report_subtest_result(result, "%s on %s", pname_str, programInterface_str); } void piglit_init(int argc, char **argv) { piglit_require_extension("GL_ARB_program_interface_query"); } enum piglit_result piglit_display(void) { GLuint prog, shader, test_cnt; bool pass = true, prg_tst; int i; /* test using an unexisting program ID */ glGetProgramInterfaceiv(1337, GL_UNIFORM, GL_MAX_NUM_ACTIVE_VARIABLES, &i); prg_tst = piglit_check_gl_error(GL_INVALID_VALUE); pass = pass && prg_tst; piglit_report_subtest_result(prg_tst ? PIGLIT_PASS : PIGLIT_FAIL, "Invalid program (undefined ID)"); /* test using a shader ID */ shader = piglit_compile_shader_text(GL_VERTEX_SHADER, vs_empty); glGetProgramInterfaceiv(shader, GL_UNIFORM, GL_MAX_NUM_ACTIVE_VARIABLES, &i); prg_tst = piglit_check_gl_error(GL_INVALID_OPERATION); pass = pass && prg_tst; piglit_report_subtest_result(prg_tst ? PIGLIT_PASS : PIGLIT_FAIL, "Invalid program (call on shader)"); /* build a valid program that will be used to run the other tests */ prog = piglit_build_simple_program(vs_empty, fs_empty); if (!piglit_link_check_status(prog)) { glDeleteProgram(prog); return PIGLIT_FAIL; } /* run all the getprograminterfaceiv tests */ test_cnt = sizeof(programInterface_subtests) / sizeof(struct subtest_t); for (i = 0; i < test_cnt; i++) { run_subtest(programInterface_subtests[i], prog, &pass); } glDeleteProgram(prog); return pass ? PIGLIT_PASS : PIGLIT_FAIL; }