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
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
26 * Validate the RFL instruction in GL_NV_fragment_program_option.
28 * \author Ian Romanick <ian.d.romanick@intel.com>
33 #include "piglit-util-gl.h"
37 /* As many columns as will fit in 640.
39 #define TEST_COLS ((640 - 1) / (BOX_SIZE + 1))
41 /* As many rows as will fit in 400.
43 #define TEST_ROWS ((400 - 1) / (BOX_SIZE + 1))
45 PIGLIT_GL_TEST_CONFIG_BEGIN
47 config
.supports_gl_compat_version
= 10;
49 config
.window_width
= (((BOX_SIZE
+1)*TEST_COLS
)+1);
50 config
.window_height
= (((BOX_SIZE
+1)*TEST_ROWS
)+1);
51 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
| PIGLIT_GL_VISUAL_DOUBLE
;
53 PIGLIT_GL_TEST_CONFIG_END
55 static const char vert_shader_source
[] =
57 "ATTRIB iPos = vertex.position;\n"
58 "OUTPUT oPos = result.position;\n"
59 "PARAM mvp[4] = { state.matrix.mvp };\n"
60 "DP4 oPos.x, mvp[0], iPos;\n"
61 "DP4 oPos.y, mvp[1], iPos;\n"
62 "DP4 oPos.z, mvp[2], iPos;\n"
63 "DP4 oPos.w, mvp[3], iPos;\n"
64 "MOV result.texcoord[0], vertex.attrib[1];\n"
65 "MOV result.texcoord[1], vertex.attrib[2];\n"
69 static const char frag_shader_source
[] =
72 "OPTION NV_fragment_program;\n"
73 "TEMP tmp, axis, direction;\n"
75 "# Since we're calcuating per-fragment and the parameters are\n"
76 "# interpolated, the parameters must be normalized.\n"
77 "DP3 tmp.x, fragment.texcoord[0], fragment.texcoord[0];\n"
78 "DP3 tmp.y, fragment.texcoord[1], fragment.texcoord[1];\n"
81 "MUL axis, tmp.x, fragment.texcoord[0];\n"
82 "MUL direction, tmp.y, fragment.texcoord[1];\n"
83 "RFL result.color, fragment.texcoord[0], fragment.texcoord[1];\n"
85 "TEMP tmp, axis, direction;\n"
86 "DP3 tmp.x, fragment.texcoord[0], fragment.texcoord[0];\n"
87 "DP3 tmp.y, fragment.texcoord[1], fragment.texcoord[1];\n"
90 "MUL axis, tmp.x, fragment.texcoord[0];\n"
91 "MUL direction, tmp.y, fragment.texcoord[1];\n"
93 /* This is the open-coded version of the RFL instruction. It was used
94 * during the development of the test. Since it maybe useful in future
95 * debugging, I am leaving it in.
97 "DP3 tmp.w, axis, axis;\n"
98 "DP3 tmp.x, axis, direction;\n"
99 "MUL tmp.x, 2.0.x, tmp.x;\n"
101 "RCP tmp.w, tmp.w;\n"
102 "MUL tmp.x, tmp.x, tmp.w;\n"
104 "MAD result.color.xyz, tmp.xxxx, axis, -direction;\n"
105 "MOV result.color.w, {0.0};\n"
111 * \name Handles to programs.
114 static GLint vert_prog
;
115 static GLint frag_prog
;
119 static GLfloat direction
[4 * TEST_ROWS
* TEST_COLS
];
120 static GLfloat axis
[4 * TEST_ROWS
* TEST_COLS
];
121 static GLfloat position
[4 * TEST_ROWS
* TEST_COLS
];
123 static const float green
[4] = { 0.0, 1.0, 0.0, 0.0 };
128 enum piglit_result result
= PIGLIT_PASS
;
133 glClear(GL_COLOR_BUFFER_BIT
);
134 glEnable(GL_FRAGMENT_PROGRAM_ARB
);
135 glEnable(GL_VERTEX_PROGRAM_ARB
);
137 glVertexAttribPointerARB(0, 4, GL_FLOAT
, GL_FALSE
, 4 * sizeof(GLfloat
),
139 glVertexAttribPointerARB(1, 4, GL_FLOAT
, GL_FALSE
, 4 * sizeof(GLfloat
),
141 glVertexAttribPointerARB(2, 4, GL_FLOAT
, GL_FALSE
, 4 * sizeof(GLfloat
),
143 glEnableVertexAttribArrayARB(0);
144 glEnableVertexAttribArrayARB(1);
145 glEnableVertexAttribArrayARB(2);
147 glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, vert_prog
);
148 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, frag_prog
);
150 glPointSize((float) BOX_SIZE
);
151 glDrawArrays(GL_POINTS
, 0, TEST_ROWS
* TEST_COLS
);
153 for (r
= 0; r
< TEST_ROWS
; r
++) {
154 for (c
= 0; c
< TEST_COLS
; c
++) {
155 const int idx
= 4 * ((r
* TEST_COLS
) + c
);
157 if (!piglit_probe_pixel_rgb(position
[idx
+ 0],
160 printf("direction = { %.2f %.2f %.2f }\n"
161 "axis = { %.2f %.2f %.2f }\n",
172 piglit_present_results();
180 return (double) rand() / (double) rand();
185 piglit_init(int argc
, char **argv
)
195 piglit_require_vertex_program();
196 piglit_require_fragment_program();
197 piglit_require_extension("GL_NV_fragment_program_option");
198 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
200 vert_prog
= piglit_compile_program(GL_VERTEX_PROGRAM_ARB
,
202 frag_prog
= piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB
,
205 glClearColor(0.5, 0.5, 0.5, 1.0);
208 for (r
= 0; r
< TEST_ROWS
; r
++) {
209 for (c
= 0; c
< TEST_COLS
; c
++) {
210 position
[i
+ 0] = (float)((BOX_SIZE
/ 2) + c
*
212 position
[i
+ 1] = (float)((BOX_SIZE
/ 2) + r
*
214 position
[i
+ 2] = 0.0f
;
215 position
[i
+ 3] = 1.0f
;
221 /* Generate a bunch of random direction vectors. Based on the random
222 * direction vector, generate an axis such that the reflection of the
223 * random vector across the axis is { 0, 1, 0 }.
226 for (i
= 0; i
< (ARRAY_SIZE(direction
) / 4); i
++) {
227 const double d
[3] = {
232 const double inv_mag_d
= 1.0 /
233 sqrt((d
[0] * d
[0]) + (d
[1] * d
[1]) + (d
[2] * d
[2]));
238 direction
[(i
* 4) + 0] = d
[0] * inv_mag_d
;
239 direction
[(i
* 4) + 1] = d
[1] * inv_mag_d
;
240 direction
[(i
* 4) + 2] = d
[2] * inv_mag_d
;
241 direction
[(i
* 4) + 3] = 0.0;
243 a
[0] = direction
[(i
* 4) + 0] + 0.0;
244 a
[1] = direction
[(i
* 4) + 1] + 1.0;
245 a
[2] = direction
[(i
* 4) + 2] + 0.0;
246 mag_a
= sqrt((a
[0] * a
[0]) + (a
[1] * a
[1]) + (a
[2] * a
[2]));
248 axis
[(i
* 4) + 0] = a
[0] / mag_a
;
249 axis
[(i
* 4) + 1] = a
[1] / mag_a
;
250 axis
[(i
* 4) + 2] = a
[2] / mag_a
;
251 axis
[(i
* 4) + 3] = 0.0;