diff options
author | Ian Romanick <ian.d.romanick@intel.com> | 2009-09-16 23:42:31 -0700 |
---|---|---|
committer | Ian Romanick <ian.d.romanick@intel.com> | 2009-09-16 23:44:15 -0700 |
commit | 1cec2f482ddbde38d7a3bf9797dcf87c08effabe (patch) | |
tree | 62cecad5ce99d7768a38b660bd35217fd4ede202 /tests/shaders/fp-condition_codes-01.c | |
parent | 2f36c3211011fe134b52924e43700c595dc526d6 (diff) |
Execerise conditional write masks in NV_fragment_program_option
Diffstat (limited to 'tests/shaders/fp-condition_codes-01.c')
-rw-r--r-- | tests/shaders/fp-condition_codes-01.c | 272 |
1 files changed, 272 insertions, 0 deletions
diff --git a/tests/shaders/fp-condition_codes-01.c b/tests/shaders/fp-condition_codes-01.c new file mode 100644 index 000000000..c48ee9bee --- /dev/null +++ b/tests/shaders/fp-condition_codes-01.c @@ -0,0 +1,272 @@ +/* + * Copyright © 2009 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 fp-condition_codes-01.c + * Validate that the correct components of the condition code register are + * set to the desired value. + * + * \author Ian Romanick <ian.d.romanick@intel.com> + */ + +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <GL/glew.h> +#if defined(__APPLE__) +#include <GLUT/glut.h> +#else +#include <GL/glut.h> +#endif +#include "piglit-util.h" +#include "piglit-framework.h" + +/* One for the reference square and one for each possible condition code. + */ +#define TEST_ROWS (1 + 6) + +/* One for each possible non-empty write mask. + */ +#define TEST_COLS (15) + +#define BOX_SIZE 16 + +int piglit_WindowMode = GLUT_DOUBLE; +int piglit_Width = (((BOX_SIZE+1)*TEST_ROWS)+1); +int piglit_Height = (((BOX_SIZE+1)*TEST_COLS)+1); + +#define INVERT_MASK(x) (~(x) & 0x0f) + +static char shader_source[64 * 1024]; + + +/** + * Strings for binary write-masks. + * + * Bit 0 corresponds to X, bit 1 to y, etc. + */ +static const char *const mask_strings[16] = { + "<empty>", + "x", + "y", + "xy", + "z", + "xz", + "yz", + "xyz", + "w", + "xw", + "yw", + "xyw", + "zw", + "xzw", + "yzw", + "xyzw", +}; + + +/** + * Strings for condition codes. + */ +static const char *const cc_strings[6] = { + "EQ", + "GE", + "GT", + "LE", + "LT", + "NE", +}; + + +/** + * Constant values that will set required condition codes + * + * The even values set the parallel condition code in \c cc_strings, and the + * odd values set something else. For example, element 4 sets GT, and element + * 5 does not (it sets LT). + */ +static const GLfloat cc_values[12] = { + 0.5, 1.0, + 1.0, 0.0, + 1.0, 0.0, + 0.0, 1.0, + 0.0, 1.0, + 0.0, 0.5 +}; + + +/** + * Source for the fragment program to render the reference box. + */ +static const char reference_shader_source[] = + "!!ARBfp1.0\n" + "MOV result.color, program.env[0];\n" + "END" + ; + +/** + * \name Handles to fragment programs. + */ +/*@{*/ +static GLint reference_prog; +static GLint progs[TEST_ROWS * TEST_COLS]; +/*@}*/ + + +void +generate_shader(unsigned cc, unsigned good_mask) +{ + unsigned len; + static const char *const swiz[16] = { + "yyyy", "xyyy", "yxyy", "xxyy", + "yyxy", "xyxy", "yxxy", "xxxy", + "yyyx", "xyyx", "yxyx", "xxyx", + "yyxx", "xyxx", "yxxx", "xxxx", + }; + + + len = sprintf(& shader_source[0], + "!!ARBfp1.0\n" + "OPTION NV_fragment_program;\n" + "PARAM good = program.env[0];\n" + "PARAM junk = program.env[1];\n" + "TEMP R0, R1, R2;\n" + "\n" + "# Create a combination of good and bad data in R0.\n" + "MOV R0, junk;\n"); + + + if (good_mask != 0) { + len += sprintf(& shader_source[len], + "MOV R0.%s, good;\n", + mask_strings[good_mask]); + } + + len += sprintf(& shader_source[len], + "\n" + "# Set the condition codes. Inputs are on the range\n" + "# [0, 1], so the range must be expanded to [-1, 1].\n" + "MADC R2, fragment.color.%s, 2.0, -1.0;\n" + "\n" + "# Create a combination of good and bad data in R1.\n" + "# The components in R0 that already have good data\n" + "# should have bad data in R1.\n" + "MOV R1, good;\n", + swiz[INVERT_MASK(good_mask)]); + + if (good_mask != 0) { + len += sprintf(& shader_source[len], + "MOV R1.%s, junk;\n", + mask_strings[good_mask]); + } + + len += sprintf(& shader_source[len], + "\n" + "# Fill remaining bits of R0 with good data from R1.\n" + "# Write that data to the shader output.\n" + "MOV R0 (%s.xyzw), R1;\n" + "MOV result.color, R0;\n" + "END\n", + cc_strings[cc]); +} + + +int +piglit_Display(void) +{ + static const GLfloat good_color[4] = { 0.9, 0.5, 0.7, 1.0 }; + static const GLfloat junk_color[4] = { 0.2, 0.2, 0.2, 1.0 }; + unsigned i = 0; + unsigned cc; + unsigned mask; + int pass = 1; + + + glClear(GL_COLOR_BUFFER_BIT); + + glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, + 0, good_color); + glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB, + 1, junk_color); + + glEnable(GL_FRAGMENT_PROGRAM_ARB); + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, reference_prog); + piglit_draw_rect(1, 1, BOX_SIZE, BOX_SIZE); + + for (cc = 0; cc < 6; cc++) { + glColor4f(cc_values[(cc * 2) + 0], cc_values[(cc * 2) + 1], + 0.0, 1.0); + + for (mask = 0; mask < 0x0f; mask++) { + const int x = ((cc + 1) * (BOX_SIZE + 1)) + 1; + const int y = (mask * (BOX_SIZE + 1)) + 1; + glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, progs[i]); + piglit_draw_rect(x, y, BOX_SIZE, BOX_SIZE); + i++; + + if (!piglit_probe_pixel_rgb(x + (BOX_SIZE / 2), + y + (BOX_SIZE / 2), + good_color)) { + if (!piglit_Automatic) + printf("CC %s with mask %s failed.\n", + cc_strings[cc], + mask_strings[mask]); + + pass = 0; + } + } + } + + glutSwapBuffers(); + return pass; +} + + +void +piglit_Init(int argc, char **argv) +{ + unsigned cc; + unsigned mask; + unsigned i; + + (void) argc; + (void) argv; + + piglit_require_fragment_program(); + piglit_require_extension("GL_NV_fragment_program_option"); + piglit_ortho_projection(piglit_Width, piglit_Height, GL_FALSE); + + reference_prog = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, + reference_shader_source); + + i = 0; + for (cc = 0; cc < 6; cc++) { + for (mask = 0; mask < 0x0f; mask++) { + generate_shader(cc, mask); + progs[i] = + piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB, + shader_source); + i++; + } + } +} |