/* * Copyright © 2014 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 active-sampler-conflict.c * Verify results of program validation when a conflicting sampler * configuration is used. * * Section 2.15.4 (Shader Execution), subheading "Validation" of the OpenGL * 2.0 spec says: * * "[INVALID_OPERATION] is generated by Begin, RasterPos, or any * command that performs an implicit Begin if: * * - any two active samplers in the current program object are * of different types, but refer to the same texture image * unit," * * This test verifies this behavior several ways. First, an invalid * configuration is constructed. When the program is in the invalid * configuration, glValidateProgram is used to determine the status. * * The program is then transitioned to a valid configuration, and * glValidateProgram is called again. * * The program is then transitioned back to the invalid configuration. * Without calling glValidateProgram, glBegin is called. This should generate * the aforementioned error. While still in the invalid state * glValidateProgram is called a third time. * * Finally, the program is transitioned back to the valid configuration. * Without calling glValidateProgram, glBegin is called. This should not * generate any error. * * All of the state flip-flopping is done in an attempt to catch * implementations that latch state in glValidateProgram and do not * re-validate in glBegin. */ #include "piglit-util-gl.h" PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 20; config.khr_no_error_support = PIGLIT_HAS_ERRORS; PIGLIT_GL_TEST_CONFIG_END static const char *fs_code = "uniform sampler2D s2;\n" "uniform sampler3D s3;\n" "\n" "void main()\n" "{\n" " gl_FragColor = texture2D(s2, vec2(0)) + texture3D(s3, vec3(0));\n" "}\n" ; static bool program_check_status(GLuint prog) { GLchar *info = NULL; GLint size; GLint ok; glValidateProgram(prog); glGetProgramiv(prog, GL_VALIDATE_STATUS, &ok); /* Some drivers return a size of 1 for an empty log. This is the size * of a log that contains only a terminating NUL character. */ glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); if (size > 1) { info = malloc(size); glGetProgramInfoLog(prog, size, NULL, info); } if (!ok) { printf("Failed to validate the program: %s\n", (info != NULL) ? info : ""); } else if (0 && info != NULL) { /* Enable this to get extra linking info. * Even if there's no link errors, the info log may * have some remarks. */ printf("Program validation warning: %s\n", info); } free(info); return ok; } void piglit_init(int argc, char **argv) { GLuint prog; GLint s2_loc; GLint s3_loc; bool pass = true; prog = piglit_build_simple_program(NULL, fs_code); s2_loc = glGetUniformLocation(prog, "s2"); if (s2_loc == -1) { fprintf(stderr, "Failed to get uniform location for s2.\n"); pass = false; } s3_loc = glGetUniformLocation(prog, "s3"); if (s3_loc == -1) { fprintf(stderr, "Failed to get uniform location for s3.\n"); pass = false; } glUseProgram(prog); /* First, try an invalid configuration. */ glUniform1i(s2_loc, 1); glUniform1i(s3_loc, 1); if (program_check_status(prog)) { fprintf(stderr, "Program was validated with conflicting " "sampler configuration.\n"); pass = false; } /* Now try a valid configuration. */ glUniform1i(s2_loc, 1); glUniform1i(s3_loc, 2); if (!program_check_status(prog)) { fprintf(stderr, "Program was not validated with non-conflicting " "sampler configuration.\n"); pass = false; } /* Switch back to the invalid configuration. Without first calling * glValidateProgramPipeline, try to draw something. Verify that * GL_INVALID_OPERATION is generated. */ glUniform1i(s2_loc, 1); glUniform1i(s3_loc, 1); glBegin(GL_POINTS); glVertex2f(0.0, 0.0); glEnd(); pass = piglit_check_gl_error(GL_INVALID_OPERATION) && pass; /* Re-validate the program. */ if (program_check_status(prog)) { fprintf(stderr, "Program was validated with conflicting " "sampler configuration (second attempt).\n"); pass = false; } /* Switch back to the valid configuration. Without first calling * glValidateProgramPipeline, try to draw something. Verify that * no error is generated. */ glUniform1i(s2_loc, 1); glUniform1i(s3_loc, 2); glBegin(GL_POINTS); glVertex2f(0.0, 0.0); glEnd(); pass = piglit_check_gl_error(GL_NO_ERROR) && pass; /* Clean up. */ glUseProgram(0); glDeleteProgram(prog); piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); } enum piglit_result piglit_display(void) { /* Not reached */ return PIGLIT_FAIL; }