2 * Copyright © 2012 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
21 * DEALINGS IN THE SOFTWARE.
24 /** @file getactiveuniformblockname.c
26 * From the GL_ARB_uniform_buffer_object spec:
28 * "An active uniform block's name string can be queried from its
29 * uniform block index by calling
31 * void GetActiveUniformBlockName(uint program,
32 * uint uniformBlockIndex,
35 * char* uniformBlockName);
37 * The string name of the uniform block identified by
38 * <uniformBlockIndex> is returned into <uniformBlockName>. The
39 * name is null-terminated. The actual number of characters
40 * written into <uniformBlockName>, excluding the null
41 * terminator, is returned in <length>. If <length> is NULL, no
44 * <bufSize> contains the maximum number of characters (including
45 * the null terminator) that will be written back to
48 * If an error occurs, nothing will be written to
49 * <uniformBlockName> or <length>.
53 * The error INVALID_VALUE is generated by GetActiveUniformsiv,
54 * GetActiveUniformName, GetActiveUniformBlockiv,
55 * GetActiveUniformBlockName, and UniformBlockBinding if
56 * <program> is not a value generated by GL.
58 * The error INVALID_VALUE is generated by GetActiveUniformName
59 * and GetActiveUniformBlockName if <bufSize> is less than zero.
61 * The error INVALID_VALUE is generated by
62 * GetActiveUniformBlockiv, GetActiveUniformBlockName, and
63 * UniformBlockBinding if <uniformBlockIndex> is greater than or
64 * equal to ACTIVE_UNIFORM_BLOCKS."
67 #include "piglit-util-gl.h"
69 PIGLIT_GL_TEST_CONFIG_BEGIN
71 config
.supports_gl_compat_version
= 10;
72 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
73 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
75 PIGLIT_GL_TEST_CONFIG_END
78 piglit_init(int argc
, char **argv
)
83 "#extension GL_ARB_uniform_buffer_object : enable\n"
84 "uniform a { float u1; };\n"
85 "uniform bbb { float u2; };\n"
86 "uniform cc { float u3; };\n"
88 " gl_FragColor = vec4(u1 + u2 + u3);\n"
92 const char *names
[3] = {"a", "bbb", "cc"};
93 bool found
[3] = {false, false, false};
95 char fill_char
= 0xd0;
97 piglit_require_extension("GL_ARB_uniform_buffer_object");
99 prog
= piglit_build_simple_program(NULL
, source
);
101 glGetProgramiv(prog
, GL_ACTIVE_UNIFORM_BLOCKS
, &blocks
);
104 for (i
= 0; i
< blocks
; i
++) {
105 GLint written_strlen
= 0;
106 GLint namelen
= 9999;
110 /* This is the size including null terminator. */
111 glGetActiveUniformBlockiv(prog
, i
, GL_UNIFORM_BLOCK_NAME_LENGTH
,
114 memset(name
, 0xd0, sizeof(name
));
115 glGetActiveUniformBlockName(prog
, i
, sizeof(name
),
116 &written_strlen
, name
);
117 if (written_strlen
>= sizeof(name
) - 1) {
119 "return strlen %d, longer than the buffer size\n",
123 } else if (name
[written_strlen
] != 0) {
124 fprintf(stderr
, "return name[%d] was %d, expected 0\n",
125 written_strlen
, name
[written_strlen
]);
128 } else if (strlen(name
) != written_strlen
) {
129 fprintf(stderr
, "return strlen was %d, but \"%s\" "
130 "has strlen %d\n", written_strlen
, name
,
136 for (name_index
= 0; name_index
< ARRAY_SIZE(names
); name_index
++) {
137 if (strcmp(names
[name_index
], name
) == 0) {
138 if (found
[name_index
]) {
140 "Uniform block \"%s\" "
141 "returned twice.\n", name
);
144 found
[name_index
] = true;
148 if (name_index
== ARRAY_SIZE(names
)) {
150 "block \"%s\" is not a known block name\n", name
);
155 if (namelen
!= written_strlen
+ 1) {
158 "GL_UNIFORM_BLOCK_NAME_LENGTH %d, expected %d\n",
159 name
, namelen
, written_strlen
+ 1);
164 /* Test for overflow by writing to a bufSize equal to
165 * strlen and checking if a null terminator or
166 * something landed past that.
168 memset(name
, fill_char
, sizeof(name
));
169 glGetActiveUniformBlockName(prog
, i
, written_strlen
,
171 if (name
[written_strlen
] != fill_char
) {
172 fprintf(stderr
, "glGetActiveUniformName overflowed: "
173 "name[%d] = 0x%02x instead of 0x%02x\n",
174 written_strlen
, name
[written_strlen
],
180 if (!piglit_khr_no_error
) {
181 no_write
= fill_char
;
182 glGetActiveUniformBlockName(0xd0d0, 0, 1, NULL
, &no_write
);
183 pass
= piglit_check_gl_error(GL_INVALID_VALUE
) && pass
;
184 if (no_write
!= fill_char
)
187 no_write
= fill_char
;
188 glGetActiveUniformBlockName(prog
, 0, -1, NULL
, &no_write
);
189 pass
= piglit_check_gl_error(GL_INVALID_VALUE
) && pass
;
190 if (no_write
!= fill_char
)
193 no_write
= fill_char
;
194 glGetActiveUniformBlockName(prog
, blocks
, 1, NULL
, &no_write
);
195 pass
= piglit_check_gl_error(GL_INVALID_VALUE
) && pass
;
196 if (no_write
!= fill_char
)
200 glDeleteProgram(prog
);
202 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);
205 enum piglit_result
piglit_display(void)