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 matrix-property-bindings.c:
26 * Access GL transformation state in ARB_vertex_program.
28 * Set matrix property bindings with the OpenGL glLoadMatrix API and access it
29 * in ARB vertex programs.
32 #include "piglit-util-gl.h"
33 #include "piglit-matrix.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
44 #define SRAND(x) srand(x)
45 #define DRAND() ((float)rand() / RAND_MAX)
47 #define SRAND(x) srand48(x)
48 #define DRAND() drand48()
52 * This vertex program compares test_param[i] against expectedi using epsilon
53 * as tolerance for all i from 0 to 3 inclusive.
54 * On match result.color is set to green, red otherwise.
56 static const char *vp_template
=
58 "PARAM epsilon = 0.00390625;\n"
59 "PARAM expected0 = {%f, %f, %f, %f};\n"
60 "PARAM expected1 = {%f, %f, %f, %f};\n"
61 "PARAM expected2 = {%f, %f, %f, %f};\n"
62 "PARAM expected3 = {%f, %f, %f, %f};\n"
63 "PARAM test_param[4] = { %s };\n"
67 "SUB tmp1, expected0, test_param[0];\n"
69 "SLT tmp1, tmp1, epsilon;\n"
70 "DP4 tmp2.x, tmp1, tmp1;\n" /* tmp2.x = 4 */
72 "SUB tmp1, expected1, test_param[1];\n"
74 "SLT tmp1, tmp1, epsilon;\n"
75 "DP4 tmp2.y, tmp1, tmp1;\n" /* tmp2.y = 4 */
77 "SUB tmp1, expected2, test_param[2];\n"
79 "SLT tmp1, tmp1, epsilon;\n"
80 "DP4 tmp2.z, tmp1, tmp1;\n" /* tmp2.z = 4 */
82 "SUB tmp1, expected3, test_param[3];\n"
84 "SLT tmp1, tmp1, epsilon;\n"
85 "DP4 tmp2.w, tmp1, tmp1;\n" /* tmp2.w = 4 */
87 "DP4 tmp2.x, tmp2, tmp2;\n" /* tmp2.x = 64 */
89 "SLT tmp1.x, tmp2.x, 64;\n" /* tmp1.x = 0 */
90 "SGE tmp1.y, tmp2.x, 64;\n" /* tmp1.y = 1 */
91 "SWZ result.color, tmp1, x, y, 0, 1;\n"
93 "MOV result.position, vertex.position;\n"
97 * Check that the constant parameter \name is equal to \m.
99 * Since we also test for derived state involving floating point computation
100 * don't test for strict equality but rather only check if the parameter's
101 * components are within and epsilon of their expected values.
104 check_prg_param_(const float *m
, const char *name
)
107 const float green
[3] = {0.0, 1.0, 0.0};
109 asprintf(&vp_text
, vp_template
, m
[0], m
[4], m
[8], m
[12], m
[1], m
[5],
110 m
[9], m
[13], m
[2], m
[6], m
[10], m
[14], m
[3], m
[7], m
[11],
112 GLuint prog
= piglit_compile_program(GL_VERTEX_PROGRAM_ARB
, vp_text
);
114 glBindProgramARB(GL_VERTEX_PROGRAM_ARB
, prog
);
116 glClear(GL_COLOR_BUFFER_BIT
);
117 piglit_draw_rect(-1, -1, 2, 2);
119 glDeleteProgramsARB(1, &prog
);
121 if (piglit_probe_pixel_rgb_silent(piglit_width
/ 2, piglit_height
/ 2,
124 printf("Failed parameter: '%s'.\n", name
);
129 * printf-like version of function above.
132 check_prg_param(const float *m
, const char *format
, ...) PRINTFLIKE(2, 3);
134 check_prg_param(const float *m
, const char *format
, ...)
139 va_start(ap
, format
);
140 vasprintf(&name
, format
, ap
);
143 const bool r
= check_prg_param_(m
, name
);
149 * Load random 16 floats between 0 and 1 into matrix \pname
150 * and return them in \m.
153 load_matrix(float m
[16], const GLenum pname
)
156 for (int i
= 0; i
< 16; ++i
)
162 * Check that matrix \pname contains the values \m.
163 * if \idx is positive add it as and index to the matrix array.
164 * if \idx is zero check both indexed and non-indexed variants.
165 * if \idx is negative check non-indexed matrix.
166 * Also check the matrix' transpose, inverse and transpose inverse.
169 check_matrix_variants(const char *prefix
, const float m
[16], const int idx
)
172 float m_T
[16], m_inv
[16], m_inv_T
[16];
174 piglit_matrix_transpose(m_T
, m
);
175 piglit_matrix_inverse(m_inv
, m
);
176 piglit_matrix_transpose(m_inv_T
, m_inv
);
179 pass
= check_prg_param(m
, "state.matrix.%s[%d]", prefix
,
181 pass
= check_prg_param(m_T
, "state.matrix.%s[%d].transpose",
182 prefix
, idx
) && pass
;
183 pass
= check_prg_param(m_inv
, "state.matrix.%s[%d].inverse",
184 prefix
, idx
) && pass
;
185 pass
= check_prg_param(m_inv_T
,
186 "state.matrix.%s[%d].invtrans", prefix
,
190 pass
= check_prg_param(m
, "state.matrix.%s", prefix
) && pass
;
191 pass
= check_prg_param(m_T
, "state.matrix.%s.transpose",
193 pass
= check_prg_param(m_inv
, "state.matrix.%s.inverse",
195 pass
= check_prg_param(m_inv_T
, "state.matrix.%s.invtrans",
203 * Load random data in matrix \pname and check it by it's shader name \name
204 * with (optional) index \idx.
207 load_and_test_matrix(const char *name
, const GLenum pname
, const int idx
)
211 load_matrix(mat
, pname
);
212 return check_matrix_variants(name
, mat
, idx
);
220 /* Test modelview and projection matrices. */
221 pass
= load_and_test_matrix("modelview", GL_MODELVIEW
, -1) && pass
;
223 pass
= load_and_test_matrix("projection", GL_PROJECTION
, -1) && pass
;
225 /* Test modelview-projection matrix. */
226 float mvp
[16], proj
[16], mview
[16];
227 load_matrix(mview
, GL_MODELVIEW
);
228 load_matrix(proj
, GL_PROJECTION
);
229 piglit_matrix_mul_matrix(mvp
, proj
, mview
);
230 pass
= check_matrix_variants("mvp", mvp
, -1) && pass
;
232 /* Test texture matrices. */
233 int max_texture_coords
;
234 glGetIntegerv(GL_MAX_TEXTURE_COORDS
, &max_texture_coords
);
235 for (int t
= 0; t
< max_texture_coords
; ++t
) {
236 glActiveTexture(GL_TEXTURE0
+ t
);
237 pass
= load_and_test_matrix("texture", GL_TEXTURE
, t
) && pass
;
240 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
244 piglit_init(int argc
, char **argv
)
246 piglit_require_extension("GL_ARB_vertex_program");
248 glEnable(GL_VERTEX_PROGRAM_ARB
);