ext_gpu_shader4: add compiler tests for everything
[piglit.git] / tests / spec / arb_vertex_program / property-bindings.c
blob381ecab2f5f9c6614712c0d0d2f385fee153d1cd
1 /*
2 * Copyright © 2017 Fabian Bieler
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 property-bindings.c: Access GL state in ARB_vertex_program.
27 * Set constant parameter bindings with the OpenGL API and access it in
28 * ARB vertex programs.
30 * Matrix state is not tested.
33 #include "piglit-util-gl.h"
35 PIGLIT_GL_TEST_CONFIG_BEGIN
37 config.supports_gl_compat_version = 13;
38 config.window_visual = PIGLIT_GL_VISUAL_RGB;
39 config.khr_no_error_support = PIGLIT_NO_ERRORS;
41 PIGLIT_GL_TEST_CONFIG_END
43 #ifdef _WIN32
44 #define SRAND(x) srand(x)
45 #define DRAND() ((float)rand() / RAND_MAX)
46 #else
47 #define SRAND(x) srand48(x)
48 #define DRAND() drand48()
49 #endif
52 * This vertex program compares test_param against expected using epsilon
53 * as tolerance. On match result.color is set to green, red otherwise.
55 static const char *vp_template =
56 "!!ARBvp1.0\n"
57 "PARAM epsilon = 0.00390625;\n"
58 "PARAM expected = {%f, %f, %f, %f};\n"
59 "PARAM test_param = %s;\n"
60 "TEMP temp;\n"
61 "SUB temp, expected, test_param;\n"
62 "ABS temp, temp;\n"
63 "SLT temp, temp, epsilon;\n"
64 "DP4 temp, temp, temp;\n"
65 "SLT temp.x, temp.x, 4;\n"
66 "SGE temp.y, temp.y, 4;\n"
67 "SWZ result.color, temp, x, y, 0, 1;\n"
68 "MOV result.position, vertex.position;\n"
69 "END";
71 /**
72 * Check that the constant parameter \name is equal to \val.
74 * Since we also test for derived state involving floating point computation
75 * don't test for strict equality but rather only check if the parameter's
76 * components are within and epsilon of their expected values.
78 static bool
79 check_prg_param_(const float *val, const char *name)
81 char *vp_text;
82 const float green[3] = {0.0, 1.0, 0.0};
84 asprintf(&vp_text, vp_template, val[0], val[1], val[2], val[3], name);
85 GLuint prog = piglit_compile_program(GL_VERTEX_PROGRAM_ARB, vp_text);
86 free(vp_text);
87 glBindProgramARB(GL_VERTEX_PROGRAM_ARB, prog);
89 glClear(GL_COLOR_BUFFER_BIT);
90 piglit_draw_rect(-1, -1, 2, 2);
92 glDeleteProgramsARB(1, &prog);
94 if (piglit_probe_pixel_rgb_silent(piglit_width / 2, piglit_height / 2,
95 green, NULL))
96 return true;
97 printf("Failed parameter: '%s'.\n", name);
98 return false;
102 * printf-like version of function above.
104 static bool
105 check_prg_param(const float *val, const char *format, ...) PRINTFLIKE(2, 3);
106 static bool
107 check_prg_param(const float *val, const char *format, ...)
109 char *name;
110 va_list ap;
112 va_start(ap, format);
113 vasprintf(&name, format, ap);
114 va_end(ap);
116 const bool r = check_prg_param_(val, name);
117 free(name);
118 return r;
121 static void
122 normalize(float *v)
124 const float norm = sqrtf(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
125 for (int i = 0; i < 3; ++i)
126 v[i] /= norm;
129 static void
130 random_vec4(float *v)
132 for (int i = 0; i < 4; ++i)
133 v[i] = DRAND();
137 * Get name fragment used in ARB program for GLenum \pname.
139 static const char *
140 enum2program(const GLenum pname)
142 switch (pname) {
143 case GL_EMISSION:
144 return "emission";
145 case GL_AMBIENT:
146 return "ambient";
147 case GL_DIFFUSE:
148 return "diffuse";
149 case GL_SPECULAR:
150 return "specular";
151 case GL_POSITION:
152 return "position";
153 case GL_S:
154 return "s";
155 case GL_T:
156 return "t";
157 case GL_R:
158 return "r";
159 case GL_Q:
160 return "q";
161 default:
162 assert(!"unexpected state enum");
163 return "";
167 enum piglit_result
168 piglit_display(void)
170 bool pass = true;
171 float val[4];
173 /* Material Property Bindings */
174 for (int s = 0; s < 2; ++s) {
175 for (int p = 0; p < 4; ++p) {
176 const GLenum pname[] = {GL_EMISSION, GL_AMBIENT,
177 GL_DIFFUSE, GL_SPECULAR};
179 random_vec4(val);
180 glMaterialfv(GL_FRONT + s, pname[p], val);
181 pass = check_prg_param(val, "state.material.%s.%s",
182 s ? "back" : "front",
183 enum2program(pname[p])) &&
184 pass;
186 /* The front material bindings are also accessible
187 * without ".front.".
189 if (s == 0)
190 pass = check_prg_param(
191 val, "state.material.%s",
192 enum2program(pname[p])) &&
193 pass;
196 val[0] = DRAND();
197 val[1] = 0;
198 val[2] = 0;
199 val[3] = 1;
200 glMaterialf(GL_FRONT + s, GL_SHININESS, val[0]);
201 pass = check_prg_param(val, "state.material.%s.shininess",
202 s ? "back" : "front") && pass;
204 if (s == 0)
205 pass = check_prg_param(val,
206 "state.material.shininess") &&
207 pass;
210 /* Light Property Bindings */
211 int max_lights;
212 glGetIntegerv(GL_MAX_LIGHTS, &max_lights);
213 for (int l = 0; l < max_lights; ++l) {
214 for (int p = 0; p < 4; ++p) {
215 const GLenum pname[] = {GL_AMBIENT, GL_DIFFUSE,
216 GL_SPECULAR, GL_POSITION};
217 random_vec4(val);
218 glLightfv(GL_LIGHT0 + l, pname[p], val);
219 pass = check_prg_param(val, "state.light[%d].%s", l,
220 enum2program(pname[p])) &&
221 pass;
224 random_vec4(val);
225 glLightf(GL_LIGHT0 + l, GL_CONSTANT_ATTENUATION, val[0]);
226 glLightf(GL_LIGHT0 + l, GL_LINEAR_ATTENUATION, val[1]);
227 glLightf(GL_LIGHT0 + l, GL_QUADRATIC_ATTENUATION, val[2]);
228 glLightf(GL_LIGHT0 + l, GL_SPOT_EXPONENT, val[3]);
229 pass = check_prg_param(val, "state.light[%d].attenuation",
230 l) && pass;
232 random_vec4(val);
233 glLightfv(GL_LIGHT0 + l, GL_SPOT_DIRECTION, val);
234 glLightf(GL_LIGHT0 + l, GL_SPOT_CUTOFF, val[3]);
235 val[3] = cosf(val[3] / 180 * M_PI);
236 pass = check_prg_param(val, "state.light[%d].spot.direction",
237 l) && pass;
239 for (int c = 0; c < 3; ++c)
240 val[c] = DRAND();
241 val[3] = 1;
242 glLightfv(GL_LIGHT0 + l, GL_POSITION, val);
243 normalize(val);
244 val[2] += 1;
245 normalize(val);
246 pass = check_prg_param(val, "state.light[%d].half", l) &&
247 pass;
250 random_vec4(val);
251 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, val);
252 pass = check_prg_param(val, "state.lightmodel.ambient") && pass;
254 for (int s = 0; s < 2; ++s) {
255 float scene_color[4];
257 for (int c = 0; c < 4; ++c)
258 scene_color[c] = val[c] = DRAND();
259 glMaterialfv(GL_FRONT + s, GL_AMBIENT, val);
260 for (int c = 0; c < 4; ++c)
261 scene_color[c] *= val[c] = DRAND();
262 glLightModelfv(GL_LIGHT_MODEL_AMBIENT, val);
263 for (int c = 0; c < 4; ++c)
264 scene_color[c] += val[c] = DRAND();
265 glMaterialfv(GL_FRONT + s, GL_EMISSION, val);
267 /* Page 63 (77 of the PDF) of the OpenGL 2.0 spec says:
269 * "The value of A produced by lighting is the alpha
270 * value associated with d_{cm}."
272 * I'm not sure if this applies to the scene color, but both
273 * Mesa and the NVIDIA driver do this.
275 random_vec4(val);
276 glMaterialfv(GL_FRONT + s, GL_DIFFUSE, val);
277 scene_color[3] = val[3];
279 pass = check_prg_param(scene_color,
280 "state.lightmodel.%s.scenecolor",
281 s ? "back" : "front") && pass;
283 if (s == 0)
284 pass = check_prg_param(
285 scene_color,
286 "state.lightmodel.scenecolor") && pass;
289 for (int s = 0; s < 2; ++s) {
290 for (int l = 0; l < max_lights; ++l) {
291 const GLenum pname[] = {GL_AMBIENT, GL_DIFFUSE,
292 GL_SPECULAR};
293 for (int p = 0; p < 3; ++p) {
294 float light_product[4];
295 for (int c = 0; c < 4; ++c)
296 light_product[c] = val[c] = DRAND();
297 glLightfv(GL_LIGHT0 + l, pname[p], val);
298 for (int c = 0; c < 4; ++c)
299 light_product[c] *= val[c] = DRAND();
300 glMaterialfv(GL_FRONT + s, pname[p], val);
301 /* XXX: I have no Idea where the spec says the
302 * alpha value of the light product is the
303 * material's alpha value, but both Mesa and
304 * the NVIDIA driver do this.
306 light_product[3] = val[3];
308 pass = check_prg_param(
309 light_product,
310 "state.lightprod[%d].%s.%s", l,
311 s ? "back" : "front",
312 enum2program(pname[p])) &&
313 pass;
315 if (s == 0)
316 pass = check_prg_param(
317 light_product,
318 "state.lightprod[%d]."
319 "%s",
321 enum2program(
322 pname[p])) &&
323 pass;
328 /* Texture Coordinate Generation Property Bindings */
329 int max_texture_coords;
330 glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_texture_coords);
331 for (int t = 0; t < max_texture_coords; ++t) {
332 const GLenum coord[] = {GL_S, GL_T, GL_R, GL_Q};
333 glActiveTexture(GL_TEXTURE0 + t);
335 for (int co = 0; co < 4; ++co) {
336 const GLenum plane[] = {GL_EYE_PLANE,
337 GL_OBJECT_PLANE};
338 const char *plane_name[] = {"eye", "object"};
339 for (int pl = 0; pl < 2; ++pl) {
340 random_vec4(val);
341 glTexGenfv(coord[co], plane[pl], val);
342 pass = check_prg_param(
343 val, "state.texgen[%d].%s.%s",
344 t, plane_name[pl],
345 enum2program(coord[co])) &&
346 pass;
347 if (t == 0)
348 pass = check_prg_param(
349 val,
350 "state.texgen.%s.%s",
351 plane_name[pl],
352 enum2program(
353 coord[co])) &&
354 pass;
359 /* Fog Property Bindings */
360 random_vec4(val);
361 glFogfv(GL_FOG_COLOR, val);
362 pass = check_prg_param(val, "state.fog.color") && pass;
364 random_vec4(val);
365 glFogf(GL_FOG_DENSITY, val[0]);
366 glFogf(GL_FOG_START, val[1]);
367 glFogf(GL_FOG_END, val[2]);
368 val[3] = 1 / (val[2] - val[1]);
369 pass = check_prg_param(val, "state.fog.params") && pass;
371 /* Clip Plane Property Bindings */
372 int max_clip_planes;
373 glGetIntegerv(GL_MAX_CLIP_PLANES, &max_clip_planes);
374 for (int cp = 0; cp < max_clip_planes; ++cp) {
375 double vald[4];
376 for (int c = 0; c < 4; ++c)
377 vald[c] = val[c] = DRAND();
378 glClipPlane(GL_CLIP_PLANE0 + cp, vald);
379 pass = check_prg_param(val, "state.clip[%d].plane", cp) &&
380 pass;
383 /* Point Property Bindings */
384 random_vec4(val);
385 glPointSize(val[0]);
386 glPointParameterf(GL_POINT_SIZE_MIN, val[1]);
387 glPointParameterf(GL_POINT_SIZE_MAX, val[2]);
388 glPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE, val[3]);
389 pass = check_prg_param(val, "state.point.size") && pass;
391 random_vec4(val);
392 val[3] = 1;
393 glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION, val);
394 pass = check_prg_param(&val[0], "state.point.attenuation") && pass;
396 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
399 void
400 piglit_init(int argc, char **argv)
402 piglit_require_extension("GL_ARB_vertex_program");
404 glEnable(GL_VERTEX_PROGRAM_ARB);
406 SRAND(17);