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
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
25 * @file built-in-uniform-state.c: Access uniform state in GLSL
27 * Set uniform state with the OpenGL API and access it in GLSL shaders.
30 #include "piglit-util-gl.h"
32 PIGLIT_GL_TEST_CONFIG_BEGIN
34 config
.supports_gl_compat_version
= 20;
35 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
;
36 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
38 PIGLIT_GL_TEST_CONFIG_END
41 #define SRAND(x) srand(x)
42 #define DRAND() ((float)rand() / RAND_MAX)
44 #define SRAND(x) srand48(x)
45 #define DRAND() drand48()
48 static const char *vs_text
=
50 " gl_Position = gl_Vertex;\n"
52 static const char *fs_float
=
54 " float epsilon = 1.0 / 256.0;\n"
55 " vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
56 " vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
59 " gl_FragColor = abs(a - b) < epsilon ? green : red;\n"
61 static const char *fs_vec3
=
63 " vec3 epsilon = vec3(1.0 / 256.0);\n"
64 " vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
65 " vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
67 " vec3 b = vec3(%f, %f, %f);\n"
68 " gl_FragColor = all(lessThan(abs(a - b), epsilon)) ? green : red;\n"
70 static const char *fs_vec4
=
72 " vec4 epsilon = vec4(1.0 / 256.0);\n"
73 " vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
74 " vec4 red = vec4(1.0, 0.0, 0.0, 1.0);\n"
76 " vec4 b = vec4(%f, %f, %f, %f);\n"
77 " gl_FragColor = all(lessThan(abs(a - b), epsilon)) ? green : red;\n"
81 * Check that the built-in shader uniform \name of type \type is equal to \val
83 * Since we also test for derived state involving floating point computation
84 * don't test for strict equality but rather only check if the uniform's
85 * components are within and espilon of their expected values.
88 check_shader_builtin_(const GLenum type
, const float *val
, const char *name
)
91 const float green
[3] = {0.0, 1.0, 0.0};
95 asprintf(&fs_text
, fs_float
, name
, *val
);
98 asprintf(&fs_text
, fs_vec3
, name
, val
[0], val
[1], val
[2]);
101 asprintf(&fs_text
, fs_vec4
, name
, val
[0], val
[1], val
[2],
108 const GLuint program
= piglit_build_simple_program(vs_text
, fs_text
);
110 glUseProgram(program
);
111 glDeleteProgram(program
);
112 glClear(GL_COLOR_BUFFER_BIT
);
113 piglit_draw_rect(-1, -1, 2, 2);
115 if (piglit_probe_pixel_rgb_silent(piglit_width
/ 2, piglit_height
/ 2,
118 printf("Failed uniform: '%s'.\n", name
);
123 * printf-like version of function above.
126 check_shader_builtin(const GLenum type
, const float *val
, const char *format
,
127 ...) PRINTFLIKE(3, 4);
129 check_shader_builtin(const GLenum type
, const float *val
, const char *format
,
135 va_start(ap
, format
);
136 vasprintf(&name
, format
, ap
);
139 const bool r
= check_shader_builtin_(type
, val
, name
);
147 const float norm
= sqrtf(v
[0] * v
[0] + v
[1] * v
[1] + v
[2] * v
[2]);
148 for (int i
= 0; i
< 3; ++i
)
153 random_vec4(float *v
)
155 for (int i
= 0; i
< 4; ++i
)
160 * Get name fragment used in GLSL for GLenum \pname.
163 enum2glsl(const GLenum pname
)
176 case GL_SPOT_EXPONENT
:
177 return "spotExponent";
180 case GL_CONSTANT_ATTENUATION
:
181 return "constantAttenuation";
182 case GL_LINEAR_ATTENUATION
:
183 return "linearAttenuation";
184 case GL_QUADRATIC_ATTENUATION
:
185 return "quadraticAttenuation";
195 assert(!"unexpected pname");
209 const float diff
= val
[1] - val
[0];
210 glDepthRangef(val
[0], val
[1]);
211 pass
= check_shader_builtin(GL_FLOAT
, val
, "gl_DepthRange.near") &&
213 pass
= check_shader_builtin(GL_FLOAT
, &val
[1], "gl_DepthRange.far") &&
215 pass
= check_shader_builtin(GL_FLOAT
, &diff
, "gl_DepthRange.diff") &&
220 glGetIntegerv(GL_MAX_CLIP_PLANES
, &max_clip_planes
);
221 for (int cp
= 0; cp
< max_clip_planes
; ++cp
) {
223 for (int c
= 0; c
< 4; ++c
)
224 vald
[c
] = val
[c
] = DRAND();
225 glClipPlane(GL_CLIP_PLANE0
+ cp
, vald
);
226 pass
= check_shader_builtin(GL_FLOAT_VEC4
, val
,
227 "gl_ClipPlane[%d]", cp
) &&
234 pass
= check_shader_builtin(GL_FLOAT
, val
, "gl_Point.size") && pass
;
237 glPointParameterf(GL_POINT_SIZE_MIN
, val
[0]);
238 pass
= check_shader_builtin(GL_FLOAT
, val
, "gl_Point.sizeMin") &&
242 glPointParameterf(GL_POINT_SIZE_MAX
, val
[0]);
243 pass
= check_shader_builtin(GL_FLOAT
, val
, "gl_Point.sizeMax") &&
247 glPointParameterf(GL_POINT_FADE_THRESHOLD_SIZE
, val
[0]);
248 pass
= check_shader_builtin(GL_FLOAT
, val
,
249 "gl_Point.fadeThresholdSize") &&
255 glPointParameterfv(GL_POINT_DISTANCE_ATTENUATION
, val
);
256 pass
= check_shader_builtin(GL_FLOAT
, &val
[0],
257 "gl_Point.distanceConstantAttenuation") &&
259 pass
= check_shader_builtin(GL_FLOAT
, &val
[1],
260 "gl_Point.distanceLinearAttenuation") &&
262 pass
= check_shader_builtin(
264 "gl_Point.distanceQuadraticAttenuation") &&
268 for (int s
= 0; s
< 2; ++s
) {
269 for (int p
= 0; p
< 4; ++p
) {
270 const GLenum pname
[] = {GL_EMISSION
, GL_AMBIENT
,
271 GL_DIFFUSE
, GL_SPECULAR
};
274 glMaterialfv(GL_FRONT
+ s
, pname
[p
], val
);
275 pass
= check_shader_builtin(GL_FLOAT_VEC4
, val
,
277 s
? "Back" : "Front",
278 enum2glsl(pname
[p
])) &&
283 glMaterialf(GL_FRONT
+ s
, GL_SHININESS
, val
[0]);
284 pass
= check_shader_builtin(GL_FLOAT
, val
,
285 "gl_%sMaterial.shininess",
286 s
? "Back" : "Front") &&
292 glGetIntegerv(GL_MAX_LIGHTS
, &max_lights
);
293 for (int l
= 0; l
< max_lights
; ++l
) {
294 for (int p
= 0; p
< 4; ++p
) {
295 const GLenum pname
[] = {GL_AMBIENT
, GL_DIFFUSE
,
296 GL_SPECULAR
, GL_POSITION
};
298 glLightfv(GL_LIGHT0
+ l
, pname
[p
], val
);
299 pass
= check_shader_builtin(GL_FLOAT_VEC4
, val
,
300 "gl_LightSource[%d].%s",
301 l
, enum2glsl(pname
[p
])) &&
306 glLightfv(GL_LIGHT0
+ l
, GL_SPOT_DIRECTION
, val
);
307 pass
= check_shader_builtin(
309 "gl_LightSource[%d].spotDirection", l
) &&
312 for (int p
= 0; p
< 5; ++p
) {
313 const GLenum pname
[] = {GL_SPOT_EXPONENT
,
315 GL_CONSTANT_ATTENUATION
,
316 GL_LINEAR_ATTENUATION
,
317 GL_QUADRATIC_ATTENUATION
};
319 glLightf(GL_LIGHT0
+ l
, pname
[p
], val
[0]);
320 pass
= check_shader_builtin(GL_FLOAT
, val
,
321 "gl_LightSource[%d].%s",
322 l
, enum2glsl(pname
[p
])) &&
326 val
[0] = DRAND() * 90;
327 glLightf(GL_LIGHT0
+ l
, GL_SPOT_CUTOFF
, val
[0]);
328 const float cos_cutoff
= cosf(val
[0] / 180 * M_PI
);
329 pass
= check_shader_builtin(
330 GL_FLOAT
, &cos_cutoff
,
331 "gl_LightSource[%d].spotCosCutoff", l
) &&
334 for (int c
= 0; c
< 3; ++c
)
337 glLightfv(GL_LIGHT0
+ l
, GL_POSITION
, val
);
341 pass
= check_shader_builtin(GL_FLOAT_VEC4
, val
,
342 "gl_LightSource[%d].halfVector",
348 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, val
);
349 pass
= check_shader_builtin(GL_FLOAT_VEC4
, val
,
350 "gl_LightModel.ambient") &&
353 /* Derived state from products of light and material. */
354 for (int s
= 0; s
< 2; ++s
) {
355 float scene_color
[4];
357 for (int c
= 0; c
< 4; ++c
)
358 scene_color
[c
] = val
[c
] = DRAND();
359 glMaterialfv(GL_FRONT
+ s
, GL_AMBIENT
, val
);
360 for (int c
= 0; c
< 4; ++c
)
361 scene_color
[c
] *= val
[c
] = DRAND();
362 glLightModelfv(GL_LIGHT_MODEL_AMBIENT
, val
);
363 for (int c
= 0; c
< 4; ++c
)
364 scene_color
[c
] += val
[c
] = DRAND();
365 glMaterialfv(GL_FRONT
+ s
, GL_EMISSION
, val
);
367 /* Page 63 (77 of the PDF) of the OpenGL 2.0 spec says:
369 * "The value of A produced by lighting is the alpha
370 * value associated with d_{cm}."
372 * I'm not sure if this applies to the scene color, but both
373 * Mesa and the NVIDIA driver do this.
376 glMaterialfv(GL_FRONT
+ s
, GL_DIFFUSE
, val
);
377 scene_color
[3] = val
[3];
379 pass
= check_shader_builtin(
380 GL_FLOAT_VEC4
, scene_color
,
381 s
? "gl_BackLightModelProduct.sceneColor"
382 : "gl_FrontLightModelProduct.sceneColor") &&
386 for (int s
= 0; s
< 2; ++s
) {
387 for (int l
= 0; l
< max_lights
; ++l
) {
388 const GLenum pname
[] = {GL_AMBIENT
, GL_DIFFUSE
,
390 for (int p
= 0; p
< 3; ++p
) {
391 float light_product
[4];
392 for (int c
= 0; c
< 4; ++c
)
393 light_product
[c
] = val
[c
] = DRAND();
394 glLightfv(GL_LIGHT0
+ l
, pname
[p
], val
);
395 for (int c
= 0; c
< 4; ++c
)
396 light_product
[c
] *= val
[c
] = DRAND();
397 glMaterialfv(GL_FRONT
+ s
, pname
[p
], val
);
398 /* XXX: I have no Idea where the spec says the
399 * alpha value of the light product is the
400 * material's alpha value, but both Mesa and
401 * the NVIDIA driver do this.
403 light_product
[3] = val
[3];
405 pass
= check_shader_builtin(
406 GL_FLOAT_VEC4
, light_product
,
407 "gl_%sLightProduct[%d].%s",
408 s
? "Back" : "Front", l
,
409 enum2glsl(pname
[p
])) &&
415 /* Texture Environment and Generation */
417 glGetIntegerv(GL_MAX_TEXTURE_UNITS
, &max_tu
);
419 glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS
, &max_tiu
);
420 const int max_textures
= MIN2(max_tu
, max_tiu
);
421 for (int t
= 0; t
< max_textures
; ++t
) {
422 glActiveTexture(GL_TEXTURE0
+ t
);
425 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
, val
);
426 pass
= check_shader_builtin(GL_FLOAT_VEC4
, val
,
427 "gl_TextureEnvColor[%d]", t
) &&
431 int max_texture_coords
;
432 glGetIntegerv(GL_MAX_TEXTURE_COORDS
, &max_texture_coords
);
433 for (int t
= 0; t
< max_texture_coords
; ++t
) {
434 const GLenum coord
[] = {GL_S
, GL_T
, GL_R
, GL_Q
};
435 glActiveTexture(GL_TEXTURE0
+ t
);
437 for (int co
= 0; co
< 4; ++co
) {
438 const GLenum plane
[] = {GL_EYE_PLANE
,
440 const char *plane_name
[] = {"Eye", "Object"};
441 for (int pl
= 0; pl
< 2; ++pl
) {
443 glTexGenfv(coord
[co
], plane
[pl
], val
);
444 pass
= check_shader_builtin(
448 enum2glsl(coord
[co
]), t
) &&
456 glFogfv(GL_FOG_COLOR
, val
);
457 pass
= check_shader_builtin(GL_FLOAT_VEC4
, val
, "gl_Fog.color") &&
462 /* Don't test infinity because shader comparisons with infinity are
469 fog_scale
= 1 / (val
[2] - val
[1]);
470 } while (isinf(fog_scale
));
472 glFogf(GL_FOG_DENSITY
, val
[0]);
473 pass
= check_shader_builtin(GL_FLOAT
, val
, "gl_Fog.density") && pass
;
475 glFogf(GL_FOG_START
, val
[1]);
476 pass
= check_shader_builtin(GL_FLOAT
, &val
[1], "gl_Fog.start") &&
479 glFogf(GL_FOG_END
, val
[2]);
480 pass
= check_shader_builtin(GL_FLOAT
, &val
[2], "gl_Fog.end") && pass
;
482 pass
= check_shader_builtin(GL_FLOAT
, &fog_scale
, "gl_Fog.scale") &&
485 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
489 piglit_init(int argc
, char **argv
)