cl: Don't use device_infos if num_device_infos == 0
[piglit.git] / tests / shaders / fp-condition_codes-01.c
bloba2b249b3ef819f9e4e2f9b94262e4ef2aaef5c7e
1 /*
2 * Copyright © 2009 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
24 /**
25 * \file fp-condition_codes-01.c
26 * Validate that the correct components of the condition code register are
27 * set to the desired value.
29 * \author Ian Romanick <ian.d.romanick@intel.com>
32 #include "piglit-util-gl.h"
34 /* One for the reference square and one for each possible condition code.
36 #define TEST_ROWS (1 + 6)
38 /* One for each possible non-empty write mask.
40 #define TEST_COLS (15)
42 #define BOX_SIZE 16
44 PIGLIT_GL_TEST_CONFIG_BEGIN
46 config.supports_gl_compat_version = 10;
48 config.window_width = (((BOX_SIZE+1)*TEST_ROWS)+1);
49 config.window_height = (((BOX_SIZE+1)*TEST_COLS)+1);
50 config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
52 PIGLIT_GL_TEST_CONFIG_END
54 #define INVERT_MASK(x) (~(x) & 0x0f)
56 static char shader_source[64 * 1024];
59 /**
60 * Strings for binary write-masks.
62 * Bit 0 corresponds to X, bit 1 to y, etc.
64 static const char *const mask_strings[16] = {
65 "<empty>",
66 "x",
67 "y",
68 "xy",
69 "z",
70 "xz",
71 "yz",
72 "xyz",
73 "w",
74 "xw",
75 "yw",
76 "xyw",
77 "zw",
78 "xzw",
79 "yzw",
80 "xyzw",
84 /**
85 * Strings for condition codes.
87 static const char *const cc_strings[6] = {
88 "EQ",
89 "GE",
90 "GT",
91 "LE",
92 "LT",
93 "NE",
97 /**
98 * Constant values that will set required condition codes
100 * The even values set the parallel condition code in \c cc_strings, and the
101 * odd values set something else. For example, element 4 sets GT, and element
102 * 5 does not (it sets LT).
104 static const GLfloat cc_values[12] = {
105 0.5, 1.0,
106 1.0, 0.0,
107 1.0, 0.0,
108 0.0, 1.0,
109 0.0, 1.0,
110 0.0, 0.5
115 * Source for the fragment program to render the reference box.
117 static const char reference_shader_source[] =
118 "!!ARBfp1.0\n"
119 "MOV result.color, program.env[0];\n"
120 "END"
124 * \name Handles to fragment programs.
126 /*@{*/
127 static GLint reference_prog;
128 static GLint progs[TEST_ROWS * TEST_COLS];
129 /*@}*/
132 void
133 generate_shader(unsigned cc, unsigned good_mask)
135 unsigned len;
136 static const char *const swiz[16] = {
137 "yyyy", "xyyy", "yxyy", "xxyy",
138 "yyxy", "xyxy", "yxxy", "xxxy",
139 "yyyx", "xyyx", "yxyx", "xxyx",
140 "yyxx", "xyxx", "yxxx", "xxxx",
144 len = sprintf(& shader_source[0],
145 "!!ARBfp1.0\n"
146 "OPTION NV_fragment_program;\n"
147 "PARAM good = program.env[0];\n"
148 "PARAM junk = program.env[1];\n"
149 "TEMP R0, R1, R2;\n"
150 "\n"
151 "# Create a combination of good and bad data in R0.\n"
152 "MOV R0, junk;\n");
155 if (good_mask != 0) {
156 len += sprintf(& shader_source[len],
157 "MOV R0.%s, good;\n",
158 mask_strings[good_mask]);
161 len += sprintf(& shader_source[len],
162 "\n"
163 "# Set the condition codes. Inputs are on the range\n"
164 "# [0, 1], so the range must be expanded to [-1, 1].\n"
165 "MADC R2, fragment.color.%s, 2.0, -1.0;\n"
166 "\n"
167 "# Create a combination of good and bad data in R1.\n"
168 "# The components in R0 that already have good data\n"
169 "# should have bad data in R1.\n"
170 "MOV R1, good;\n",
171 swiz[INVERT_MASK(good_mask)]);
173 if (good_mask != 0) {
174 len += sprintf(& shader_source[len],
175 "MOV R1.%s, junk;\n",
176 mask_strings[good_mask]);
179 len += sprintf(& shader_source[len],
180 "\n"
181 "# Fill remaining bits of R0 with good data from R1.\n"
182 "# Write that data to the shader output.\n"
183 "MOV R0 (%s.xyzw), R1;\n"
184 "MOV result.color, R0;\n"
185 "END\n",
186 cc_strings[cc]);
190 enum piglit_result
191 piglit_display(void)
193 static const GLfloat good_color[4] = { 0.9, 0.5, 0.7, 1.0 };
194 static const GLfloat junk_color[4] = { 0.2, 0.2, 0.2, 1.0 };
195 unsigned i = 0;
196 unsigned cc;
197 unsigned mask;
198 enum piglit_result result = PIGLIT_PASS;
201 glClear(GL_COLOR_BUFFER_BIT);
203 glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
204 0, good_color);
205 glProgramEnvParameter4fvARB(GL_FRAGMENT_PROGRAM_ARB,
206 1, junk_color);
208 glEnable(GL_FRAGMENT_PROGRAM_ARB);
209 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, reference_prog);
210 piglit_draw_rect(1, 1, BOX_SIZE, BOX_SIZE);
212 for (cc = 0; cc < 6; cc++) {
213 glColor4f(cc_values[(cc * 2) + 0], cc_values[(cc * 2) + 1],
214 0.0, 1.0);
216 for (mask = 0; mask < 0x0f; mask++) {
217 const int x = ((cc + 1) * (BOX_SIZE + 1)) + 1;
218 const int y = (mask * (BOX_SIZE + 1)) + 1;
219 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB, progs[i]);
220 piglit_draw_rect(x, y, BOX_SIZE, BOX_SIZE);
221 i++;
223 if (!piglit_probe_pixel_rgb(x + (BOX_SIZE / 2),
224 y + (BOX_SIZE / 2),
225 good_color)) {
226 if (!piglit_automatic)
227 printf("CC %s with mask %s failed.\n",
228 cc_strings[cc],
229 mask_strings[mask]);
231 result = PIGLIT_FAIL;
236 piglit_present_results();
237 return result;
241 void
242 piglit_init(int argc, char **argv)
244 unsigned cc;
245 unsigned mask;
246 unsigned i;
248 (void) argc;
249 (void) argv;
251 piglit_require_fragment_program();
252 piglit_require_extension("GL_NV_fragment_program_option");
253 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
255 reference_prog = piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB,
256 reference_shader_source);
258 i = 0;
259 for (cc = 0; cc < 6; cc++) {
260 for (mask = 0; mask < 0x0f; mask++) {
261 generate_shader(cc, mask);
262 progs[i] =
263 piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB,
264 shader_source);
265 i++;