1 /*
2 * Copyright © 2019 Advanced Micro Devices, Inc.
3 *
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:
10 *
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.
14 *
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.
22 */
23
24 #include "piglit-util-gl.h"
25
26 static int
parse_gl_version(int argc,char ** argv)27 parse_gl_version(int argc, char** argv)
28 {
29 int version;
30 if (argc < 2) {
31 piglit_loge("Usage: %s 12|30\n", argv[0]);
32 exit(1);
33 }
34 version = atoi(argv[1]);
35 if (version != 12 && version != 30) {
36 piglit_loge("Usage: %s 12|30\n", argv[0]);
37 exit(1);
38 }
39 return version;
40 }
41
42 static int gl_compat_version;
43
44 PIGLIT_GL_TEST_CONFIG_BEGIN
45
46 gl_compat_version = parse_gl_version(argc, argv);
47 config.supports_gl_compat_version = gl_compat_version;
48 config.khr_no_error_support = PIGLIT_HAS_ERRORS;
49
50 PIGLIT_GL_TEST_CONFIG_END
51
52 static GLint max_units;
53 static GLint max_tex_coords;
54
55 struct get_float_indexed_t {
56 void (*get_float_fn) (GLenum, GLuint, GLfloat *);
57 const char* name;
58 int min_gl_compat_version;
59 };
60 struct get_double_indexed_t {
61 void (*get_double_fn) (GLenum, GLuint, GLdouble *);
62 const char* name;
63 int min_gl_compat_version;
64 };
65 struct get_pointer_indexed_t {
66 void (*get_pointer_fn) (GLenum, GLuint, GLvoid **);
67 const char* name;
68 int min_gl_compat_version;
69 };
70
71
72 static enum piglit_result
test_GetBooleanIndexedvEXT(void * data)73 test_GetBooleanIndexedvEXT(void* data)
74 {
75 static const GLenum targets[] = {
76 /*
77 * Targets for which:
78 * glGetBooleanIndexedvEXT(target, index, params)
79 * is equivalent to:
80 * glActiveTexture(GL_TEXTURE0+index);
81 * glGetBooleanv(target, params);
82 */
83 GL_TEXTURE_1D,
84 GL_TEXTURE_2D,
85 GL_TEXTURE_3D,
86 GL_TEXTURE_CUBE_MAP,
87
88 /* Separator */
89 GL_NONE,
90
91 /*
92 * Targets for which:
93 * glGetBooleanIndexedvEXT(target, index, params)
94 * is equivalent to:
95 * glClientActiveTexture(GL_TEXTURE0+index);
96 * glGetBooleanv(target, params);
97 */
98 GL_TEXTURE_COORD_ARRAY
99 };
100 int i, index;
101 GLboolean value, expected_value;
102 bool useActiveTexture = true;
103
104 for (i = 0; i < ARRAY_SIZE(targets); i++) {
105 if (targets[i] == GL_NONE) {
106 useActiveTexture = false;
107 continue;
108 }
109
110 if (useActiveTexture) {
111 index = rand() % max_units;
112 } else {
113 index = rand() % max_tex_coords;
114 }
115
116 glGetBooleanIndexedvEXT(targets[i], index, &value);
117
118 if (useActiveTexture) {
119 glActiveTexture(GL_TEXTURE0 + index);
120 } else {
121 glClientActiveTexture(GL_TEXTURE0 + index);
122 }
123 glGetBooleanv(targets[i], &expected_value);
124
125 if (value != expected_value || !piglit_check_gl_error(GL_NO_ERROR)) {
126 piglit_loge("glGetBooleanIndexedvEXT(%s, %d, ...) failed. Expected: %d but got %d\n",
127 piglit_get_gl_enum_name(targets[i]),
128 index,
129 expected_value,
130 value);
131 return PIGLIT_FAIL;
132 }
133 }
134
135 return PIGLIT_PASS;
136 }
137
138 static enum piglit_result
test_GetIntegerIndexedvEXT(void * data)139 test_GetIntegerIndexedvEXT(void* data)
140 {
141 static const GLenum targets[] = {
142 GL_TEXTURE_BINDING_1D, GL_TEXTURE_BINDING_1D_ARRAY,
143 GL_TEXTURE_BINDING_2D, GL_TEXTURE_BINDING_2D_ARRAY,
144 GL_TEXTURE_BINDING_3D, GL_TEXTURE_BINDING_CUBE_MAP
145 };
146 int i;
147 int value, expected_value;
148
149 for (i = 0; i < ARRAY_SIZE(targets); i++) {
150 int index = rand() % max_units;
151 glActiveTexture(GL_TEXTURE0 + (index + 1) % max_units);
152
153 glGetIntegerIndexedvEXT(targets[i], index, &value);
154
155 glActiveTexture(GL_TEXTURE0 + index);
156 glGetIntegerv(targets[i], &expected_value);
157
158 if (value != expected_value || !piglit_check_gl_error(GL_NO_ERROR)) {
159 piglit_loge("glGetIntegerIndexedvEXT(%s, %d, ...) failed. Expected: %d but got %d\n",
160 piglit_get_gl_enum_name(targets[i]),
161 index,
162 expected_value,
163 value);
164 return PIGLIT_FAIL;
165 }
166 }
167 return PIGLIT_PASS;
168 }
169
170 static enum piglit_result
test_GetFloatIndexedvEXT(void * data)171 test_GetFloatIndexedvEXT(void* data)
172 {
173 static const GLenum targets[] = {
174 GL_TEXTURE_MATRIX, GL_TRANSPOSE_TEXTURE_MATRIX,
175 };
176 int i;
177 float value[16], expected_value[16];
178
179 struct get_float_indexed_t* test = (struct get_float_indexed_t*) data;
180
181 if (gl_compat_version < test->min_gl_compat_version) {
182 return PIGLIT_SKIP;
183 }
184
185 for (i = 0; i < ARRAY_SIZE(targets); i++) {
186 int index = rand() % max_tex_coords;
187 glActiveTexture(GL_TEXTURE0 + (index + 1) % max_tex_coords);
188
189 test->get_float_fn(targets[i], index, value);
190
191 glActiveTexture(GL_TEXTURE0 + index);
192 glGetFloatv(targets[i], expected_value);
193
194 if (memcmp(value, expected_value, sizeof(value)) != 0 ||
195 !piglit_check_gl_error(GL_NO_ERROR)) {
196 piglit_loge("%s(%s, %d, ...) failed.\n",
197 test->name,
198 piglit_get_gl_enum_name(targets[i]),
199 index);
200 return PIGLIT_FAIL;
201 }
202 }
203 return PIGLIT_PASS;
204 }
205
206 static enum piglit_result
test_GetDoubleIndexedvEXT(void * data)207 test_GetDoubleIndexedvEXT(void* data)
208 {
209 static const GLenum targets[] = {
210 GL_TEXTURE_MATRIX, GL_TRANSPOSE_TEXTURE_MATRIX,
211 };
212 int i;
213 double value[16], expected_value[16];
214
215 struct get_double_indexed_t* test = (struct get_double_indexed_t*) data;
216 if (gl_compat_version < test->min_gl_compat_version) {
217 return PIGLIT_SKIP;
218 }
219
220 for (i = 0; i < ARRAY_SIZE(targets); i++) {
221 int index = rand() % max_tex_coords;
222 glActiveTexture(GL_TEXTURE0 + (index + 1) % max_tex_coords);
223
224 test->get_double_fn(targets[i], index, value);
225
226 glActiveTexture(GL_TEXTURE0 + index);
227 glGetDoublev(targets[i], expected_value);
228
229 if (memcmp(value, expected_value, sizeof(value)) != 0 ||
230 !piglit_check_gl_error(GL_NO_ERROR)) {
231 piglit_loge("%s(%s, %d, ...) failed.\n",
232 test->name,
233 piglit_get_gl_enum_name(targets[i]),
234 index);
235 return PIGLIT_FAIL;
236 }
237 }
238 return PIGLIT_PASS;
239 }
240
241 static enum piglit_result
test_GetPointerIndexedvEXT(void * data)242 test_GetPointerIndexedvEXT(void* data)
243 {
244 /* The GL_EXT_direct_state_access spec says:
245 *
246 * The following query
247 *
248 * void GetPointerIndexedvEXT(enum pname, uint index, void **params);
249 *
250 * is equivalent (assuming no errors) to the following:
251 *
252 * int savedClientActiveTexture;
253 *
254 * GetIntegerv(CLIENT_ACTIVE_TEXTURE, &savedClientActiveTexture);
255 * ClientActiveTexture(TEXTURE0+index);
256 * GetPointerv(pname, params);
257 * ClientActiveTexture(savedClientActiveTexture);
258 *
259 * [...] when the pname parameter is TEXTURE_COORD_ARRAY_POINTER.
260 *
261 */
262 static const GLenum invalid_pnames[] = {
263 GL_COLOR_ARRAY_POINTER, GL_EDGE_FLAG_ARRAY_POINTER,
264 GL_FOG_COORD_ARRAY_POINTER, GL_FEEDBACK_BUFFER_POINTER,
265 GL_INDEX_ARRAY_POINTER, GL_NORMAL_ARRAY_POINTER,
266 GL_SECONDARY_COLOR_ARRAY_POINTER, GL_SELECTION_BUFFER_POINTER,
267 GL_VERTEX_ARRAY_POINTER
268 };
269 int i;
270 void* ptr, *expected_ptr;
271
272 int index = rand() % max_tex_coords;
273
274 struct get_pointer_indexed_t* test = (struct get_pointer_indexed_t*) data;
275 if (gl_compat_version < test->min_gl_compat_version) {
276 return PIGLIT_SKIP;
277 }
278
279 glActiveTexture(GL_TEXTURE0 + (index + 1) % max_tex_coords);
280
281 test->get_pointer_fn(GL_TEXTURE_COORD_ARRAY_POINTER, index, &ptr);
282
283 glActiveTexture(GL_TEXTURE0 + index);
284
285 glGetPointerv(GL_TEXTURE_COORD_ARRAY_POINTER, &expected_ptr);
286
287 if (expected_ptr != ptr || !piglit_check_gl_error(GL_NO_ERROR)) {
288 return PIGLIT_FAIL;
289 }
290
291 for (i = 0; i < ARRAY_SIZE(invalid_pnames); i++) {
292 glGetPointerIndexedvEXT(invalid_pnames[i], index, &ptr);
293
294 if (!piglit_check_gl_error(GL_INVALID_ENUM)) {
295 piglit_loge("glGetPointerIndexedvEXT(%s, ..., ...) should emit GL_INVALID_ENUM.\n",
296 piglit_get_gl_enum_name(invalid_pnames[i]));
297 return PIGLIT_FAIL;
298 }
299 }
300 return PIGLIT_PASS;
301 }
302
303 void
piglit_init(int argc,char ** argv)304 piglit_init(int argc, char **argv)
305 {
306 piglit_require_extension("GL_EXT_direct_state_access");
307
308 glGetIntegerv(GL_MAX_TEXTURE_COORDS, &max_tex_coords);
309 glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &max_units);
310
311 /* The GL_EXT_direct_state_access spec says:
312 *
313 * Add OpenGL 3.0-style aliases for the version 1.0 commands
314 * and queries that have "Indexed" in the name. OpenGL 3.0 has a
315 * convention where an "i" indexed indexed commands and queries.
316 * For example, glGetFloati_v and glGetFloatIndexedvEXT are
317 * identical queries
318 *
319 * So glGetFloatIndexedvEXT/GetFloati_vEXT, GetDoubleIndexedvEXT/GetDoublei_vEXT
320 * and GetPointerIndexedvEXT/GetPointeri_vEXT use the same subtest
321 * where data describes which function is being tested.
322 */
323
324 const struct get_float_indexed_t get_float_12 = {
325 glGetFloatIndexedvEXT, "GetFloatIndexedvEXT", 12
326 };
327 const struct get_float_indexed_t get_float_30 = {
328 glGetFloati_vEXT, "GetFloati_vEXT", 30
329 };
330 const struct get_double_indexed_t get_double_12 = {
331 glGetDoubleIndexedvEXT, "GetDoubleIndexedvEXT", 12
332 };
333 const struct get_double_indexed_t get_double_30 = {
334 glGetDoublei_vEXT, "GetDoublei_vEXT", 30
335 };
336 const struct get_pointer_indexed_t get_pointer_12 = {
337 glGetPointerIndexedvEXT, "GetPointerIndexedvEXT", 12
338 };
339 const struct get_pointer_indexed_t get_pointer_30 = {
340 glGetPointeri_vEXT, "GetPointeri_vEXT", 30
341 };
342
343 const struct piglit_subtest tests[] = {
344 {
345 "GetBooleanIndexedvEXT",
346 NULL,
347 test_GetBooleanIndexedvEXT
348 },
349 {
350 "GetIntegerIndexedvEXT",
351 NULL,
352 test_GetIntegerIndexedvEXT
353 },
354 {
355 "GetFloatIndexedvEXT",
356 NULL,
357 test_GetFloatIndexedvEXT,
358 (void*) &get_float_12
359 },
360 {
361 "GetFloati_vEXT",
362 NULL,
363 test_GetFloatIndexedvEXT,
364 (void*) &get_float_30,
365 },
366 {
367 "GetDoubleIndexedvEXT",
368 NULL,
369 test_GetDoubleIndexedvEXT,
370 (void*) &get_double_12
371 },
372 {
373 "GetDoublei_vEXT",
374 NULL,
375 test_GetDoubleIndexedvEXT,
376 (void*) &get_double_30,
377 },
378 {
379 "GetPointerIndexedvEXT",
380 NULL,
381 test_GetPointerIndexedvEXT,
382 (void*) &get_pointer_12
383 },
384 {
385 "GetPointeri_vEXT",
386 NULL,
387 test_GetPointerIndexedvEXT,
388 (void*) &get_pointer_30,
389 },
390 {
391 NULL
392 }
393 };
394 piglit_report_result(piglit_run_selected_subtests(tests, NULL, 0, PIGLIT_PASS));
395 }
396
397 enum piglit_result
piglit_display(void)398 piglit_display(void)
399 {
400 /* UNREACHABLE */
401 return PIGLIT_FAIL;
402 }