2 * Copyright (c) 2013 Timothy Arceri <t_arceri@yahoo.com.au>
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 * on the rights to use, copy, modify, merge, publish, distribute, sub
8 * license, and/or sell copies of the Software, and to permit persons to whom
9 * the 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,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 * NON-INFRINGEMENT. IN NO EVENT SHALL AUTHORS AND/OR THEIR SUPPLIERS
19 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25 #include "piglit-util-gl.h"
27 static const char *TestLabel
= "Test Label";
28 #define TestLabelLen 10
30 PIGLIT_GL_TEST_CONFIG_BEGIN
32 #ifdef PIGLIT_USE_OPENGL
33 config
.supports_gl_compat_version
= 11;
34 #else /* using GLES */
35 config
.supports_gl_es_version
= 11;
38 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
39 config
.khr_no_error_support
= PIGLIT_HAS_ERRORS
;
41 PIGLIT_GL_TEST_CONFIG_END
49 /* <label> will be null-terminated. The actual number of
50 * characters written into <label>,
51 * excluding the null terminator, is returned in <length>.
54 check_label_and_length(char *label
, int length
, GLenum object
)
57 const char *name
= piglit_get_gl_enum_name(object
);
59 printf("Checking label and length of %s object\n", name
);
61 if (!piglit_check_gl_error(GL_NO_ERROR
))
64 if (length
!= TestLabelLen
|| (strcmp(TestLabel
, label
) != 0)) {
65 fprintf(stderr
, "Label or length does not match in %s object\n", name
);
66 printf(" actual label: %s actual length: %i\n", label
, length
);
67 printf(" expected label: %s expected length: %i\n", TestLabel
, TestLabelLen
);
74 /* trivial tests to get/set labels on all the different types of objects */
76 test_object_label_types()
79 GLsizei length
[numObjects
]; /* create a fresh variable for each object to test */
80 GLchar label
[numObjects
][TestLabelLen
+ 1];
83 enum test_object_indices
{
84 BUFFER_IDX
, SHADER_IDX
, PROGRAM_IDX
, VERTEX_ARRAY_IDX
, RENDERBUFFER_IDX
,
85 FRAMEBUFFER_IDX
, QUERY_IDX
, PROGRAM_PIPELINE_IDX
, TRANSFORM_FEEDBACK_IDX
,
86 SAMPLER_IDX
, TEXTURE_IDX
, DISPLAY_LIST_IDX
94 #ifdef PIGLIT_USE_OPENGL
95 GLuint programPipeline
;
97 GLuint transformFeedback
;
104 glGenBuffers(1, &buffer
);
105 glBindBuffer(GL_ARRAY_BUFFER
, buffer
);
106 glLabelObjectEXT(GL_BUFFER_OBJECT_EXT
, buffer
, 0, TestLabel
);
107 glGetObjectLabelEXT(GL_BUFFER_OBJECT_EXT
, buffer
, TestLabelLen
+ 1, &length
[BUFFER_IDX
], label
[BUFFER_IDX
]);
109 pass
= check_label_and_length(label
[BUFFER_IDX
], length
[BUFFER_IDX
],
112 glDeleteBuffers(1, &buffer
);
114 if (piglit_get_gl_version() >= 20) {
116 shader
= glCreateShader(GL_FRAGMENT_SHADER
);
117 glLabelObjectEXT(GL_SHADER_OBJECT_EXT
, shader
, 0, TestLabel
);
118 glGetObjectLabelEXT(GL_SHADER_OBJECT_EXT
, shader
, TestLabelLen
+ 1,
119 &length
[SHADER_IDX
], label
[SHADER_IDX
]);
121 pass
= check_label_and_length(label
[SHADER_IDX
], length
[SHADER_IDX
],
124 glDeleteShader(shader
);
127 program
= glCreateProgram();
128 glLabelObjectEXT(GL_PROGRAM_OBJECT_EXT
, program
, 0, TestLabel
);
129 glGetObjectLabelEXT(GL_PROGRAM_OBJECT_EXT
, program
, TestLabelLen
+ 1,
130 &length
[PROGRAM_IDX
], label
[PROGRAM_IDX
]);
132 pass
= check_label_and_length(label
[PROGRAM_IDX
], length
[PROGRAM_IDX
],
135 glDeleteProgram(program
);
138 /* GL or GLES >= 3.0 supports vertex arrays*/
139 if (piglit_get_gl_version() >= 30) {
140 /* Test VERTEX_ARRAY */
141 glGenVertexArrays(1, &vertexArray
);
142 glBindVertexArray(vertexArray
);
143 glLabelObjectEXT(GL_VERTEX_ARRAY_OBJECT_EXT
, vertexArray
, 0, TestLabel
);
144 glGetObjectLabelEXT(GL_VERTEX_ARRAY_OBJECT_EXT
, vertexArray
, TestLabelLen
+ 1,
145 &length
[VERTEX_ARRAY_IDX
], label
[VERTEX_ARRAY_IDX
]);
147 pass
= check_label_and_length(label
[VERTEX_ARRAY_IDX
], length
[VERTEX_ARRAY_IDX
],
148 GL_VERTEX_ARRAY
) && pass
;
150 glDeleteVertexArrays(1, &vertexArray
);
153 /* GLES supports render buffer and frame buffer since 2.0 */
154 if (piglit_is_gles() || piglit_get_gl_version() >= 30) {
155 /* Test RENDERBUFFER */
156 glGenRenderbuffers(1, &renderbuffer
);
157 glBindRenderbuffer(GL_RENDERBUFFER
, renderbuffer
);
158 glLabelObjectEXT(GL_RENDERBUFFER
, renderbuffer
, 0, TestLabel
);
159 glGetObjectLabelEXT(GL_RENDERBUFFER
, renderbuffer
, TestLabelLen
+ 1,
160 &length
[RENDERBUFFER_IDX
], label
[RENDERBUFFER_IDX
]);
162 pass
= check_label_and_length(label
[RENDERBUFFER_IDX
], length
[RENDERBUFFER_IDX
],
163 GL_RENDERBUFFER
) && pass
;
165 glDeleteRenderbuffers(1, &renderbuffer
);
167 /* Test FRAMEBUFFER */
168 glGenFramebuffers(1, &framebuffer
);
169 glBindFramebuffer(GL_FRAMEBUFFER
, framebuffer
);
170 glLabelObjectEXT(GL_FRAMEBUFFER
, framebuffer
, 0, TestLabel
);
171 glGetObjectLabelEXT(GL_FRAMEBUFFER
, framebuffer
, TestLabelLen
+ 1,
172 &length
[FRAMEBUFFER_IDX
], label
[FRAMEBUFFER_IDX
]);
174 pass
= check_label_and_length(label
[FRAMEBUFFER_IDX
], length
[FRAMEBUFFER_IDX
],
175 GL_FRAMEBUFFER
) && pass
;
177 glDeleteFramebuffers(1, &framebuffer
);
180 /* GLES >= 3.0 or GL compat */
181 if (piglit_is_extension_supported("GL_ARB_occlusion_query") ||
182 piglit_get_gl_version() >= 30) {
184 glGenQueries(1, &query
);
185 if (piglit_is_gles()) {
186 glBeginQuery(GL_ANY_SAMPLES_PASSED
, query
);
187 glEndQuery(GL_ANY_SAMPLES_PASSED
);
189 glBeginQuery(GL_SAMPLES_PASSED
, query
);
190 glEndQuery(GL_SAMPLES_PASSED
);
192 glLabelObjectEXT(GL_QUERY_OBJECT_EXT
, query
, 0, TestLabel
);
193 glGetObjectLabelEXT(GL_QUERY_OBJECT_EXT
, query
, TestLabelLen
+ 1, &length
[QUERY_IDX
], label
[QUERY_IDX
]);
195 pass
= check_label_and_length(label
[QUERY_IDX
], length
[QUERY_IDX
],
198 glDeleteQueries(1, &query
);
201 #ifdef PIGLIT_USE_OPENGL
202 /* Test PROGRAM_PIPELINE */
203 if (piglit_is_extension_supported("GL_ARB_separate_shader_objects")) {
204 glGenProgramPipelines(1, &programPipeline
);
205 glBindProgramPipeline(programPipeline
);
206 glLabelObjectEXT(GL_PROGRAM_PIPELINE_OBJECT_EXT
, programPipeline
, 0, TestLabel
);
207 glGetObjectLabelEXT(GL_PROGRAM_PIPELINE_OBJECT_EXT
, programPipeline
, TestLabelLen
+ 1,
208 &length
[PROGRAM_PIPELINE_IDX
], label
[PROGRAM_PIPELINE_IDX
]);
210 pass
= check_label_and_length(label
[PROGRAM_PIPELINE_IDX
], length
[PROGRAM_PIPELINE_IDX
],
211 GL_PROGRAM_PIPELINE
) && pass
;
213 glDeleteProgramPipelines(1, &programPipeline
);
215 #endif /* PIGLIT_USE_OPENGL */
217 /* Test TRANSFORM_FEEDBACK */
218 if ((piglit_is_gles() && piglit_get_gl_version() >= 30) ||
219 piglit_is_extension_supported("GL_ARB_transform_feedback2")) {
220 glGenTransformFeedbacks(1, &transformFeedback
);
221 glBindTransformFeedback(GL_TRANSFORM_FEEDBACK
, transformFeedback
);
222 glLabelObjectEXT(GL_TRANSFORM_FEEDBACK
, transformFeedback
, 0, TestLabel
);
223 glGetObjectLabelEXT(GL_TRANSFORM_FEEDBACK
, transformFeedback
, TestLabelLen
+ 1,
224 &length
[TRANSFORM_FEEDBACK_IDX
], label
[TRANSFORM_FEEDBACK_IDX
]);
226 pass
= check_label_and_length(label
[TRANSFORM_FEEDBACK_IDX
], length
[TRANSFORM_FEEDBACK_IDX
],
227 GL_TRANSFORM_FEEDBACK
) && pass
;
229 glDeleteTransformFeedbacks(1, &transformFeedback
);
233 if ((piglit_is_gles() && piglit_get_gl_version() >= 30) ||
234 piglit_is_extension_supported("GL_ARB_sampler_objects")) {
235 glGenSamplers(1, &sampler
);
236 glBindSampler(0, sampler
);
237 glLabelObjectEXT(GL_SAMPLER
, sampler
, 0, TestLabel
);
238 glGetObjectLabelEXT(GL_SAMPLER
, sampler
, TestLabelLen
+ 1, &length
[SAMPLER_IDX
], label
[SAMPLER_IDX
]);
240 pass
= check_label_and_length(label
[SAMPLER_IDX
], length
[SAMPLER_IDX
],
243 glDeleteSamplers(1, &sampler
);
247 glGenTextures(1, &texture
);
248 glBindTexture(GL_TEXTURE_2D
, texture
);
249 glLabelObjectEXT(GL_TEXTURE
, texture
, 0, TestLabel
);
250 glGetObjectLabelEXT(GL_TEXTURE
, texture
, TestLabelLen
+ 1, &length
[TEXTURE_IDX
], label
[TEXTURE_IDX
]);
252 pass
= check_label_and_length(label
[TEXTURE_IDX
], length
[TEXTURE_IDX
],
255 glDeleteTextures(1, &texture
);
265 GLuint invalidBufferName
;
266 GLchar label
[TestLabelLen
+ 1];
269 puts("Test LabelObject");
271 glGenBuffers(1, &buffer
);
273 /* If <label> is NULL, any debug label is effectively removed from the object.
275 glLabelObjectEXT(GL_BUFFER
, buffer
, 0, TestLabel
);
276 glLabelObjectEXT(GL_BUFFER
, buffer
, 0, NULL
);
277 glGetObjectLabelEXT(GL_BUFFER
, buffer
, TestLabelLen
+ 1, &length
, label
);
279 if (length
!= 0 || (strcmp("", label
) != 0)) {
280 fprintf(stderr
, "Setting label to NULL should remove the label\n");
281 printf(" actual label: %s actual length: %i\n", label
, length
);
285 /* An INVALID_ENUM error is generated by ObjectLabel if <identifier> is not
286 * one of the object types.
288 glLabelObjectEXT(GL_ARRAY_BUFFER
, buffer
, 0, TestLabel
);
290 if (!piglit_check_gl_error(GL_INVALID_ENUM
)) {
291 fprintf(stderr
, "GL_INVALID_ENUM should be generated when the LabelObject identifier is invalid\n");
295 /* INVALID_VALUE is generated by LabelObjectEXT if <length> is less than zero. */
296 glLabelObjectEXT(GL_BUFFER
, buffer
, -1, TestLabel
);
298 if (!piglit_check_gl_error(GL_INVALID_VALUE
)) {
299 fprintf(stderr
, "GL_INVALID_VALUE should be generated when the LabelObject length is less than 0\n");
303 /* INVALID_OPERATION is generated by LabelObjectEXT
304 * if the type of <object> does not match <type>.
306 invalidBufferName
= buffer
;
307 glDeleteBuffers(1, &buffer
);
308 glLabelObjectEXT(GL_BUFFER
, invalidBufferName
, 0, TestLabel
);
310 if (!piglit_check_gl_error(GL_INVALID_OPERATION
)) {
311 fprintf(stderr
, "GL_INVALID_OPERATION should be generated when the LabelObject name is invalid\n");
319 test_get_object_label()
323 GLuint buffers
[numBuffers
];
324 GLuint invalidBufferName
;
325 GLchar label
[TestLabelLen
+ 1];
328 enum test_object_indices
{
329 TEST_BUFSIZE_IDX
, TEST_NO_LABEL_IDX
, TEST_NULL_LABEL_IDX
, TEST_NULL_LENGTH_IDX
332 puts("Test GetObjectLabel");
334 glGenBuffers(numBuffers
, buffers
);
336 /* The maximum number of characters that may
337 * be written into <label>, including the null terminator, is specified by
340 glBindBuffer(GL_ARRAY_BUFFER
, buffers
[TEST_BUFSIZE_IDX
]);
341 glLabelObjectEXT(GL_BUFFER
, buffers
[TEST_BUFSIZE_IDX
], 0, TestLabel
);
342 glGetObjectLabelEXT(GL_BUFFER
, buffers
[TEST_BUFSIZE_IDX
], TestLabelLen
, &length
, label
);
344 if (length
!= 9 || (strcmp("Test Labe", label
) != 0)) {
345 fprintf(stderr
, "BufSize should limit the maximum label length to 9\n");
346 printf(" actual label: %s actual length: %i\n", label
, length
);
350 /* If no debug label was specified for the object then <label>
351 * will contain a null-terminated empty string, and zero will be returned
354 glBindBuffer(GL_ARRAY_BUFFER
, buffers
[TEST_NO_LABEL_IDX
]);
355 glGetObjectLabelEXT(GL_BUFFER
, buffers
[TEST_NO_LABEL_IDX
], TestLabelLen
+ 1, &length
, label
);
357 if (length
!= 0 || (strcmp("", label
) != 0)) {
358 fprintf(stderr
, "Label should be empty and length 0\n");
359 printf(" actual label: %s actual length: %i\n", label
, length
);
363 /* If <label> is NULL and <length> is non-NULL then no string
364 * will be returned and the length of the label will be returned in
367 glBindBuffer(GL_ARRAY_BUFFER
, buffers
[TEST_NULL_LABEL_IDX
]);
368 glLabelObjectEXT(GL_BUFFER
, buffers
[TEST_NULL_LABEL_IDX
], 0, TestLabel
);
369 glGetObjectLabelEXT(GL_BUFFER
, buffers
[TEST_NULL_LABEL_IDX
], TestLabelLen
+ 1, &length
, NULL
);
371 if (length
!= TestLabelLen
) {
372 fprintf(stderr
, "Label length should be %i\n", TestLabelLen
);
373 printf(" actual length: %i\n", length
);
377 /* If <length> is NULL, no length is returned.
379 glBindBuffer(GL_ARRAY_BUFFER
, buffers
[TEST_NULL_LENGTH_IDX
]);
380 glLabelObjectEXT(GL_BUFFER
, buffers
[TEST_NULL_LENGTH_IDX
], 0, TestLabel
);
381 glGetObjectLabelEXT(GL_BUFFER
, buffers
[TEST_NULL_LENGTH_IDX
], TestLabelLen
+ 1, NULL
, label
);
383 if (strcmp(TestLabel
, label
) != 0) {
384 fprintf(stderr
, "Label doent match expected string when length NULL\n");
385 printf(" label: %s expected: %s\n", label
, TestLabel
);
389 /* An INVALID_ENUM error is generated by GetObjectLabel if identifier is not
390 * one of the valid object types
392 glGetObjectLabelEXT(GL_ARRAY_BUFFER
, buffers
[TEST_NULL_LENGTH_IDX
], TestLabelLen
+ 1, &length
, label
);
394 if (!piglit_check_gl_error(GL_INVALID_ENUM
)) {
395 fprintf(stderr
, "GL_INVALID_ENUM should be generated when GetObjectLabel identifier is invalid\n");
399 /* INVALID_VALUE is generated by GetObjectLabelEXT if <bufSize> is less than zero. */
400 glGetObjectLabelEXT(GL_BUFFER
, buffers
[TEST_NULL_LENGTH_IDX
], -1, &length
, label
);
402 if (!piglit_check_gl_error(GL_INVALID_VALUE
)) {
403 fprintf(stderr
, "GL_INVALID_VALUE should be generated when GetObjectLabel bufSize is less than 0\n");
407 /* INVALID_OPERATION is generated by GetObjectLabelEXT
408 * if the type of <object> does not match <type>.
410 invalidBufferName
= buffers
[TEST_NULL_LENGTH_IDX
];
411 glDeleteBuffers(numBuffers
, buffers
);
412 glGetObjectLabelEXT(GL_BUFFER
, invalidBufferName
, TestLabelLen
+ 1, &length
, label
);
414 if (!piglit_check_gl_error(GL_INVALID_OPERATION
)) {
415 fprintf(stderr
, "GL_INVALID_OPERATION should be generated when GetObjectLabel name is invalid\n");
422 void piglit_init(int argc
, char **argv
)
426 #ifdef PIGLIT_USE_OPENGL
427 piglit_require_gl_version(11);
429 piglit_require_extension("GL_EXT_debug_label");
431 pass
= test_object_label_types() && pass
;
432 pass
= test_object_label() && pass
;
433 pass
= test_get_object_label() && pass
;
435 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);