2 * Copyright © 2015 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 DEALINGS
25 * \file object-namespace-pollution.c
26 * Verify that the GL implementation does not pollute the object namespace.
28 * At least through Mesa 11.1.0, Mesa drivers that use "meta" have some
29 * problems with respect to the OpenGL object namespace. Many places inside
30 * meta allocate objects using a mechanism similar to \c glGen*. This poses
31 * serious problems for applications that create objects without using the
32 * associated \c glGen* function (so called "user generated names").
34 * Section 3.8.12 (Texture Objects) of the OpenGL 2.1 (May 16, 2008) spec
39 * void GenTextures( sizei n, uint *textures );
41 * returns n previously unused texture object names in textures. These
42 * names are marked as used, for the purposes of GenTextures only, but
43 * they acquire texture state and a dimensionality only when they are
44 * first bound, just as if they were unused."
46 * Calling glBindTexture on an unused name makes that name be used. An
47 * application can mix user generated names and GL generated names only if it
48 * is careful not to reuse names that were previously returned by
49 * glGenTextures. In practice this means that all user generated names must
50 * be used (i.e., bound) before calling glGenTextures.
52 * This effectively means that the GL implementation (or, realistically, GL
53 * middleware) is \b never allowed to use glGenTextures because the
54 * application cannot know what names were returned.
56 * This applies to most kinds of GL objects.
63 * - vertex programs (from GL_ARB_vertex_program)
64 * - fragment programs (from GL_ARB_fragment_program)
65 * - vertex arrays (from GL_APPLE_vertex_array_object)
66 * - fragment shaders (from GL_ATI_fragment_shader)
68 * Many object types (ARB vertex array objects, transform feedback objects,
69 * program pipeline objects, GLSL shader / program objects, Intel performance
70 * query objects, sampler objects, etc.) forbid user generated names.
72 * Some object types (NVIDIA or APPLE fences, EXT vertex shaders, NVIDIA
73 * transform feedback objects) could probably also suffer from this problem.
74 * However, Mesa does not support these objects, so we don't need to test
77 * GL_AMD_performance_monitor does not specify whether or not user generated
80 * This test attempts to observe this kind of invalid behavior. First a GL
81 * operation is performed that may need to create an object. Then the test
82 * creates several objects with user generated names. Finally, the GL
83 * operations are performed again. If the GL implemented generated new names
84 * for the purpose of the operations, those names will likely conflict with
85 * one of the user generated names. This should be observable in one of three
88 * - When the test tries to create the object, the object will already exist.
89 * This is detected by the \c glIs* functions.
91 * - After the second call to the GL operation, the application's object will
92 * have modified state.
94 * - The second call to the GL operation will fail to perform correctly
95 * because the application modified its data.
97 * Only the first two methods are employed by this test. This should catch
98 * the vast majority of possible failures. Verifying the correctness of the
99 * GL operation would add a lot of complexity to the test.
102 #include "piglit-util-gl.h"
104 PIGLIT_GL_TEST_CONFIG_BEGIN
106 config
.supports_gl_compat_version
= 12;
107 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_DEPTH
| PIGLIT_GL_VISUAL_STENCIL
;
108 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
110 PIGLIT_GL_TEST_CONFIG_END
112 struct enum_value_pair
{
117 #define BUFFER_OFFSET(i) ((char *)NULL + (i))
120 * Spare objects used by test cases.
122 * Some tests need to use objects for the GL operation begin tested. For
123 * example, the \c glGenerateMipmap test needs a texture. These objects
124 * cannot be created using \c glGen* because that would conflict with the rest
125 * of the test. Instead statically allocate object names starting with some
126 * high number that we hope the GL won't use or generate during the test.
128 #define FIRST_SPARE_OBJECT 600
131 * Linear feedback shift register random number generator
133 * Simple Galois LFSRs that is loosely based on
134 * https://en.wikipedia.org/wiki/Linear_feedback_shift_register
136 * The value of \c state is updated to reflect the new state of the LFSR.
137 * This new value should be passed in for the next iteration.
140 * Either 0 or 1 based on the incoming value of \c state.
143 lfsr(uint16_t *state
)
145 unsigned output
= *state
& 1;
147 /* For an LFSR, zero is a fixed point, and that's no good for
148 * generating additional values.
152 /* If the output bit is zero, just shift it out. If the output bit is
153 * one, shift it out and toggle some bits.
155 *state
= (*state
>> 1) ^ (-output
& 0x0000B400);
161 * Fill some memory with pseudorandom values
163 * Using two seed values, a pair of LFSRs are used to generate pseudorandom
164 * values to fill the specified memory buffer. Separate invocations with
165 * identical \c bytes, \c seed1, and \c seed2 parameters will generate
166 * identical data. This can be used generate data to initialize a buffer and
167 * regenerate the same data to validate the buffer.
170 generate_random_data(void *_output
, size_t bytes
, uint16_t seed1
,
173 uint8_t *output
= (uint8_t *) _output
;
175 /* If the two seeds are the same, the whole "random" buffer will be
176 * filled with zeroes.
178 assert(seed1
!= seed2
);
180 for (unsigned i
= 0; i
< bytes
; i
++) {
183 for (unsigned bit
= 0; bit
< 8; bit
++) {
185 byte
|= lfsr(&seed1
) ^ lfsr(&seed2
);
192 /** \name Methods for operating on buffer objects */
194 #define BUFFER_DATA_SIZE 1024
197 create_buffer(unsigned name
)
199 uint8_t data
[BUFFER_DATA_SIZE
];
201 if (!piglit_is_extension_supported("GL_ARB_vertex_buffer_object") &&
202 piglit_get_gl_version() < 14) {
203 printf("%s requires vertex buffer objects.\n", __func__
);
204 piglit_report_result(PIGLIT_SKIP
);
207 generate_random_data(data
, sizeof(data
), GL_ARRAY_BUFFER
, name
);
209 if (glIsBuffer(name
)) {
210 printf("\t%s,%d: %u is already a buffer\n",
211 __func__
, __LINE__
, name
);
215 glBindBuffer(GL_ARRAY_BUFFER
, name
);
216 glBufferData(GL_ARRAY_BUFFER
, sizeof(data
), data
, GL_STATIC_DRAW
);
217 glBindBuffer(GL_ARRAY_BUFFER
, 0);
219 return piglit_check_gl_error(GL_NO_ERROR
);
223 validate_buffer(unsigned name
)
225 static const struct enum_value_pair test_vectors
[] = {
226 { GL_BUFFER_SIZE
, BUFFER_DATA_SIZE
},
227 { GL_BUFFER_USAGE
, GL_STATIC_DRAW
},
228 { GL_BUFFER_ACCESS
, GL_READ_WRITE
},
229 { GL_BUFFER_MAPPED
, GL_FALSE
},
232 uint8_t data
[BUFFER_DATA_SIZE
];
235 if (!glIsBuffer(name
)) {
236 printf("\t%s,%d: %u is not a buffer\n",
237 __func__
, __LINE__
, name
);
241 glBindBuffer(GL_ARRAY_BUFFER
, name
);
243 for (unsigned i
= 0; i
< ARRAY_SIZE(test_vectors
); i
++) {
246 glGetBufferParameteriv(GL_ARRAY_BUFFER
,
247 test_vectors
[i
].value
,
250 if (got
!= test_vectors
[i
].expected
) {
251 printf("\t%s,%d: %s of %u: got 0x%x, expected 0x%x\n",
253 piglit_get_gl_enum_name(test_vectors
[i
].value
),
254 name
, got
, test_vectors
[i
].expected
);
259 generate_random_data(data
, sizeof(data
), GL_ARRAY_BUFFER
, name
);
260 map
= glMapBuffer(GL_ARRAY_BUFFER
, GL_READ_ONLY
);
262 if (memcmp(map
, data
, sizeof(data
)) != 0) {
263 printf("\t%s,%d: Data mismatch in %u\n",
264 __func__
, __LINE__
, name
);
268 printf("\t%s,%d: Unable to map %u\n",
269 __func__
, __LINE__
, name
);
273 glUnmapBuffer(GL_ARRAY_BUFFER
);
275 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
281 /** \name Methods for operating on framebuffer objects */
284 create_framebuffer(unsigned name
)
286 if (!piglit_is_extension_supported("GL_EXT_framebuffer_object")) {
287 printf("%s requires GL_EXT_framebuffer_object.\n", __func__
);
288 piglit_report_result(PIGLIT_SKIP
);
291 if (glIsFramebufferEXT(name
)) {
292 printf("\t%s,%d: %u is already a framebuffer\n",
293 __func__
, __LINE__
, name
);
297 glBindFramebufferEXT(GL_FRAMEBUFFER
, name
);
298 glBindFramebufferEXT(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
300 return piglit_check_gl_error(GL_NO_ERROR
);
304 validate_framebuffer(unsigned name
)
306 static const struct enum_value_pair test_vectors
[] = {
307 { GL_COLOR_ATTACHMENT0
, 0 },
308 { GL_DEPTH_ATTACHMENT
, 0 },
309 { GL_STENCIL_ATTACHMENT
, 0 },
313 if (!glIsFramebufferEXT(name
)) {
314 printf("\t%s,%d: %u is not a framebuffer\n",
315 __func__
, __LINE__
, name
);
319 glBindFramebufferEXT(GL_FRAMEBUFFER
, name
);
321 for (unsigned i
= 0; i
< ARRAY_SIZE(test_vectors
); i
++) {
324 glGetFramebufferAttachmentParameterivEXT(GL_FRAMEBUFFER
,
325 test_vectors
[i
].value
,
326 GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
,
329 if (got
!= test_vectors
[i
].expected
) {
330 printf("\t%s,%d: %s of %u: got 0x%x, expected 0x%x\n",
332 piglit_get_gl_enum_name(test_vectors
[i
].value
),
333 name
, got
, test_vectors
[i
].expected
);
338 glBindFramebufferEXT(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
340 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
344 /** \name Methods for operating on vertex or fragment program objects */
347 generate_program_source(GLenum target
, unsigned key
)
351 if (target
== GL_VERTEX_PROGRAM_ARB
) {
352 const char *position
;
356 const char *mv_invtrans
;
358 if ((key
& 2) != 0) {
359 mvp
= "state.matrix.mvp";
361 "DP4 p.x, mvp[0], vp;\n"
362 "DP4 p.y, mvp[1], vp;\n"
363 "DP4 p.z, mvp[2], vp;\n"
364 "DP4 p.w, mvp[3], vp;\n"
367 mvp
= "state.matrix.mvp.transpose";
369 "MUL r0, mvp[0], vp.xxxx;\n"
370 "MAD r0, mvp[1], vp.yyyy, r0;\n"
371 "MAD r0, mvp[2], vp.zzzz, r0;\n"
372 "MAD r0, mvp[3], vp.wwww, r0;\n"
377 if ((key
& 4) != 0) {
378 mv_invtrans
= "state.matrix.modelview.invtrans";
380 "DP3 n.x, mv_invtrans[0], vn;\n"
381 "DP3 n.y, mv_invtrans[1], vn;\n"
382 "DP3 n.z, mv_invtrans[2], vn;\n"
385 mv_invtrans
= "state.matrix.modelview.inverse";
387 "MUL r0.xyz, mv_invtrans[0], vn;\n"
388 "MAD r0.xyz, mv_invtrans[1], vn, r0;\n"
389 "MAD r0.xyz, mv_invtrans[2], vn, r0;\n"
390 "SWZ n, r0, x, y, z, 0;\n"
394 if ((key
& 8) != 0) {
396 "# Output the color\n"
397 "MOV t, vertex.color;\n"
401 "# Output the texture coordinate\n"
402 "MOV t, vertex.texcoord[0];\n"
406 (void)!asprintf(&source
,
408 "# Program key 0x%04x\n"
409 "ATTRIB vp = vertex.position;\n"
410 "ATTRIB vn = vertex.normal;\n"
411 "PARAM mvp[4] = { %s.row[0..3] };\n"
412 "PARAM mv_invtrans[3] = { %s.row[0..2] };\n"
413 "OUTPUT p = result.position;\n"
414 "OUTPUT n = result.texcoord[0];\n"
415 "OUTPUT t = result.texcoord[1];\n"
418 "# Transform the vertex to clip coordinates.\n"
421 "# Transform the normal to eye coordinates.\n"
432 } else if (target
== GL_FRAGMENT_PROGRAM_ARB
) {
434 const char *half_dir
;
435 const char *light_dir
;
437 if ((key
& 2) != 0) {
438 tex
= "TEX r0, t, texture[0], 2D;";
440 tex
= "TEX r0, t, texture[0], 1D;";
443 if ((key
& 4) != 0) {
444 light_dir
= "program.env[0]";
446 light_dir
= "state.light[0].position";
449 if ((key
& 4) != 0) {
450 half_dir
= "program.env[1]";
452 half_dir
= "state.light[0].half";
455 (void)!asprintf(&source
,
457 "# Program key 0x%04x\n"
458 "ATTRIB n = fragment.texcoord[0];\n"
459 "ATTRIB t = fragment.texcoord[1];\n"
460 "PARAM light_dir = %s;\n"
461 "PARAM half_dir = %s;\n"
462 "OUTPUT c = result.color;\n"
465 "# Sample the texture\n"
468 "# Compute lighting\n"
469 "DP3 r1.x, n, light_dir;\n"
470 "DP3 r1.y, n, half_dir;\n"
474 "# Combine lighting and texture\n"
475 "MUL r0, r1.y, r0;\n"
476 "ADD c.xyz, r1.z, r0;\n"
484 printf("Unknown program target %s (0x%04x) in %s.\n",
485 piglit_get_gl_enum_name(target
), target
,
487 piglit_report_result(PIGLIT_FAIL
);
494 * Selects a program target based on the key and the supported extensions.
497 select_program_target(unsigned key
)
501 if (piglit_is_extension_supported("GL_ARB_vertex_program")) {
502 target
= GL_VERTEX_PROGRAM_ARB
;
505 if (piglit_is_extension_supported("GL_ARB_fragment_program")) {
506 if (target
== 0 || (key
& 1) == 0)
507 target
= GL_FRAGMENT_PROGRAM_ARB
;
514 create_program(unsigned name
)
517 const GLenum target
= select_program_target(name
);
520 printf("%s requires GL_ARB_vertex_program or "
521 "GL_ARB_fragment_program.\n",
523 piglit_report_result(PIGLIT_SKIP
);
526 if (glIsProgramARB(name
)) {
527 printf("\t%s,%d: %u is already a program\n",
528 __func__
, __LINE__
, name
);
532 glBindProgramARB(target
, name
);
534 source
= generate_program_source(target
, name
);
535 glProgramStringARB(target
, GL_PROGRAM_FORMAT_ASCII_ARB
,
536 strlen(source
), source
);
540 glBindProgramARB(target
, 0);
542 return piglit_check_gl_error(GL_NO_ERROR
);
546 validate_program(unsigned name
)
549 const GLenum target
= select_program_target(name
);
550 char *expected
= generate_program_source(target
, name
);
551 const int expected_length
= strlen(expected
);
555 if (!glIsProgramARB(name
)) {
556 printf("\t%s,%d: %u is not a program\n",
557 __func__
, __LINE__
, name
);
562 glBindProgramARB(target
, name
);
564 /* The GL_ARB_vertex_program spec does not say whether or not length
565 * includes a terminating NUL. It says:
567 * "If <pname> is PROGRAM_LENGTH_ARB ... GetProgramivARB returns
568 * one integer holding the program string length (in bytes)
569 * ... for the program object currently bound to <target>."
571 * and, with respect to glGetProgramStringARB it says:
573 * "<n> ubytes are returned into the array program where <n> is
574 * the length of the program in ubytes, as returned by
575 * GetProgramivARB when <pname> is PROGRAM_LENGTH_ARB."
577 glGetProgramivARB(target
,
578 GL_PROGRAM_LENGTH_ARB
,
580 if (length
!= expected_length
&& length
!= (expected_length
+ 1)) {
581 printf("\t%s,%d: Program %u length invalid: got %d, expected "
585 length
, expected_length
, expected_length
+ 1);
589 got
= calloc(length
, sizeof(char));
590 glGetProgramStringARB(target
,
591 GL_PROGRAM_STRING_ARB
,
594 if (memcmp(expected
, got
, expected_length
) != 0) {
595 printf("\t%s,%d: %u source mismatch\n",
604 glBindProgramARB(target
, 0);
606 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
610 /** \name Methods for operating on renderbuffer objects */
613 create_renderbuffer(unsigned name
)
615 if (!piglit_is_extension_supported("GL_EXT_framebuffer_object")) {
616 printf("%s requires GL_EXT_framebuffer_object.\n", __func__
);
617 piglit_report_result(PIGLIT_SKIP
);
620 if (glIsRenderbufferEXT(name
)) {
621 printf("\t%s,%d: %u is already a renderbuffer\n",
622 __func__
, __LINE__
, name
);
626 glBindRenderbufferEXT(GL_RENDERBUFFER
, name
);
627 glRenderbufferStorageEXT(GL_RENDERBUFFER
, GL_RGBA8
,
628 17 /* width */, 15 /* height */);
630 glBindRenderbufferEXT(GL_RENDERBUFFER
, 0);
632 return piglit_check_gl_error(GL_NO_ERROR
);
636 validate_renderbuffer(unsigned name
)
638 static const struct enum_value_pair test_vectors
[] = {
639 { GL_RENDERBUFFER_WIDTH
, 17 },
640 { GL_RENDERBUFFER_HEIGHT
, 15 },
641 { GL_RENDERBUFFER_INTERNAL_FORMAT
, GL_RGBA8
},
642 { GL_RENDERBUFFER_DEPTH_SIZE
, 0 },
643 { GL_RENDERBUFFER_STENCIL_SIZE
, 0 },
647 if (!glIsRenderbufferEXT(name
)) {
648 printf("\t%s,%d: %u is not a renderbuffer\n",
649 __func__
, __LINE__
, name
);
653 glBindRenderbufferEXT(GL_RENDERBUFFER
, name
);
655 for (unsigned i
= 0; i
< ARRAY_SIZE(test_vectors
); i
++) {
658 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER
,
659 test_vectors
[i
].value
,
662 if (got
!= test_vectors
[i
].expected
) {
663 printf("\t%s,%d: %s of %u: got 0x%x, expected 0x%x\n",
665 piglit_get_gl_enum_name(test_vectors
[i
].value
),
666 name
, got
, test_vectors
[i
].expected
);
671 glBindRenderbufferEXT(GL_RENDERBUFFER
, 0);
673 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
677 /** \name Methods for operating on texture objects */
679 #define TEXTURE_DATA_SIZE (16 * 16 * sizeof(GLuint))
682 create_texture(unsigned name
)
684 uint8_t data
[TEXTURE_DATA_SIZE
];
686 generate_random_data(data
, sizeof(data
), GL_TEXTURE_2D
, name
);
688 if (glIsTexture(name
)) {
689 printf("\t%s,%d: %u is already a texture\n",
690 __func__
, __LINE__
, name
);
694 glBindTexture(GL_TEXTURE_2D
, name
);
695 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0, GL_RGBA
,
696 GL_UNSIGNED_INT_8_8_8_8
, data
);
697 glBindTexture(GL_TEXTURE_2D
, 0);
699 return piglit_check_gl_error(GL_NO_ERROR
);
703 validate_texture(unsigned name
)
705 static const struct enum_value_pair tex_test_vectors
[] = {
706 { GL_TEXTURE_WRAP_S
, GL_REPEAT
},
707 { GL_TEXTURE_WRAP_T
, GL_REPEAT
},
708 { GL_TEXTURE_WRAP_R
, GL_REPEAT
},
709 { GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_LINEAR
},
710 { GL_TEXTURE_MAG_FILTER
, GL_LINEAR
},
711 { GL_TEXTURE_BASE_LEVEL
, 0 },
712 { GL_TEXTURE_MAX_LEVEL
, 1000 },
714 static const struct enum_value_pair tex_level_test_vectors
[] = {
715 { GL_TEXTURE_WIDTH
, 16 },
716 { GL_TEXTURE_HEIGHT
, 16 },
717 { GL_TEXTURE_INTERNAL_FORMAT
, GL_RGBA8
},
720 uint8_t data
[TEXTURE_DATA_SIZE
];
721 uint8_t texels
[TEXTURE_DATA_SIZE
];
723 if (!glIsTexture(name
)) {
724 printf("\t%s,%d: %u is not a texture\n",
725 __func__
, __LINE__
, name
);
729 glBindTexture(GL_TEXTURE_2D
, name
);
731 for (unsigned i
= 0; i
< ARRAY_SIZE(tex_test_vectors
); i
++) {
734 glGetTexParameteriv(GL_TEXTURE_2D
,
735 tex_test_vectors
[i
].value
,
738 if (got
!= tex_test_vectors
[i
].expected
) {
739 printf("\t%s,%d: %s of %u: got 0x%x, expected 0x%x\n",
741 piglit_get_gl_enum_name(tex_test_vectors
[i
].value
),
742 name
, got
, tex_test_vectors
[i
].expected
);
747 for (unsigned i
= 0; i
< ARRAY_SIZE(tex_level_test_vectors
); i
++) {
750 glGetTexLevelParameteriv(GL_TEXTURE_2D
, 0,
751 tex_level_test_vectors
[i
].value
,
754 if (got
!= tex_level_test_vectors
[i
].expected
) {
755 printf("\t%s,%d: %s of %u: got 0x%x, expected 0x%x\n",
757 piglit_get_gl_enum_name(tex_level_test_vectors
[i
].value
),
758 name
, got
, tex_level_test_vectors
[i
].expected
);
763 /* Try to use glGetnTexImageARB. If the test's 16x16 texture was
764 * replaced with something larger, the call to glGetTexImage will
765 * probably segfault. This could be worked around, but it doesn't
768 * If the texture size did change, the glGetTexLevelParameteriv loop
769 * above will have already detected it.
771 generate_random_data(data
, sizeof(data
), GL_TEXTURE_2D
, name
);
772 if (piglit_is_extension_supported("GL_ARB_robustness")) {
773 /* Note: if sizeof(texels) is less than the size of the image,
774 * glGetnTexImageARB will generate GL_INVALID_OPERATION.
776 glGetnTexImageARB(GL_TEXTURE_2D
, 0, GL_RGBA
,
777 GL_UNSIGNED_INT_8_8_8_8
,
778 sizeof(texels
), texels
);
780 glGetTexImage(GL_TEXTURE_2D
, 0, GL_RGBA
,
781 GL_UNSIGNED_INT_8_8_8_8
,
785 if (memcmp(texels
, data
, sizeof(data
)) != 0) {
786 printf("\t%s,%d: Data mismatch in %u\n",
787 __func__
, __LINE__
, name
);
791 glBindTexture(GL_TEXTURE_2D
, 0);
793 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
797 /** \name Methods for operating on Apple vertex array objects */
799 static float dummy_vao_data
[257];
801 static const int vao_vertex_size
[] = { 2, 3, 4 };
802 static const int vao_color_size
[] = { 3, 4 };
803 static const int vao_texture_size
[] = { 1, 2, 3, 4 };
804 static const GLenum vao_vertex_type
[] = { GL_SHORT
, GL_INT
, GL_FLOAT
, GL_DOUBLE
};
805 static const GLenum vao_normal_type
[] = { GL_BYTE
, GL_SHORT
, GL_INT
, GL_FLOAT
, GL_DOUBLE
};
806 static const GLenum vao_color_type
[] = {
807 GL_BYTE
, GL_UNSIGNED_BYTE
,
808 GL_SHORT
, GL_UNSIGNED_SHORT
,
809 GL_INT
, GL_UNSIGNED_INT
,
814 #define PICK(a, i) a[i % ARRAY_SIZE(a)]
815 #define STRIDE(x) (((x) % 16) * sizeof(int))
817 /* 4 arrays, and each has at most 4 values. */
818 #define VAO_DATA_SIZE (4 * 4)
821 create_vertex_array(unsigned name
)
823 uint8_t data
[VAO_DATA_SIZE
];
825 if (!piglit_is_extension_supported("GL_APPLE_vertex_array_object")) {
826 printf("%s requires GL_APPLE_vertex_array_object.\n", __func__
);
827 piglit_report_result(PIGLIT_SKIP
);
830 if (glIsVertexArrayAPPLE(name
)) {
831 printf("\t%s,%d: %u is already a vertex array\n",
832 __func__
, __LINE__
, name
);
836 glBindVertexArrayAPPLE(name
);
838 generate_random_data(data
,
840 GL_VERTEX_ARRAY_BINDING_APPLE
,
843 glVertexPointer(PICK(vao_vertex_size
, data
[0]),
844 PICK(vao_vertex_type
, data
[1]),
846 &dummy_vao_data
[data
[3]]);
847 glNormalPointer(PICK(vao_normal_type
, data
[4]),
849 &dummy_vao_data
[data
[6]]);
850 glColorPointer(PICK(vao_color_size
, data
[7]),
851 PICK(vao_color_type
, data
[8]),
853 &dummy_vao_data
[data
[10]]);
854 glTexCoordPointer(PICK(vao_texture_size
, data
[11]),
855 PICK(vao_vertex_type
, data
[12]),
857 &dummy_vao_data
[data
[14]]);
859 glBindVertexArrayAPPLE(0);
861 return piglit_check_gl_error(GL_NO_ERROR
);
865 check_integer_query(GLenum pname
, int expected
, unsigned name
,
870 glGetIntegerv(pname
, &got
);
871 if (got
!= expected
) {
872 printf("\t%s,%d: %s of %u: got 0x%x, expected 0x%x\n",
874 piglit_get_gl_enum_name(pname
),
884 check_pointer_query(GLenum pname
, const void *expected
, unsigned name
,
889 glGetPointerv(pname
, &got
);
890 if (got
!= expected
) {
891 printf("\t%s,%d: %s of %u: got %p, expected %p\n",
893 piglit_get_gl_enum_name(pname
),
903 validate_vertex_array(unsigned name
)
905 uint8_t data
[VAO_DATA_SIZE
];
908 if (!piglit_is_extension_supported("GL_APPLE_vertex_array_object"))
911 if (!glIsVertexArrayAPPLE(name
)) {
912 printf("\t%s,%d: %u is not a vertex array\n",
913 __func__
, __LINE__
, name
);
917 glBindVertexArrayAPPLE(name
);
919 generate_random_data(data
,
921 GL_VERTEX_ARRAY_BINDING_APPLE
,
924 pass
= check_integer_query(GL_VERTEX_ARRAY_SIZE
,
925 PICK(vao_vertex_size
, data
[0]),
928 pass
= check_integer_query(GL_VERTEX_ARRAY_TYPE
,
929 PICK(vao_vertex_type
, data
[1]),
932 pass
= check_integer_query(GL_VERTEX_ARRAY_STRIDE
,
936 pass
= check_pointer_query(GL_VERTEX_ARRAY_POINTER
,
937 &dummy_vao_data
[data
[3]],
941 pass
= check_integer_query(GL_NORMAL_ARRAY_TYPE
,
942 PICK(vao_normal_type
, data
[4]),
945 pass
= check_integer_query(GL_NORMAL_ARRAY_STRIDE
,
949 pass
= check_pointer_query(GL_NORMAL_ARRAY_POINTER
,
950 &dummy_vao_data
[data
[6]],
954 pass
= check_integer_query(GL_COLOR_ARRAY_SIZE
,
955 PICK(vao_color_size
, data
[7]),
958 pass
= check_integer_query(GL_COLOR_ARRAY_TYPE
,
959 PICK(vao_color_type
, data
[8]),
962 pass
= check_integer_query(GL_COLOR_ARRAY_STRIDE
,
966 pass
= check_pointer_query(GL_COLOR_ARRAY_POINTER
,
967 &dummy_vao_data
[data
[10]],
971 pass
= check_integer_query(GL_TEXTURE_COORD_ARRAY_SIZE
,
972 PICK(vao_texture_size
, data
[11]),
975 pass
= check_integer_query(GL_TEXTURE_COORD_ARRAY_TYPE
,
976 PICK(vao_vertex_type
, data
[12]),
979 pass
= check_integer_query(GL_TEXTURE_COORD_ARRAY_STRIDE
,
983 pass
= check_pointer_query(GL_TEXTURE_COORD_ARRAY_POINTER
,
984 &dummy_vao_data
[data
[14]],
988 glBindVertexArrayAPPLE(0);
989 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
993 /** \name GL operation wrapper functions. */
998 GLint old_unpack_alignment
;
999 uint8_t bitmap
[16 * 16 / 8];
1001 glGetIntegerv(GL_UNPACK_ALIGNMENT
, &old_unpack_alignment
);
1002 glPixelStorei(GL_UNPACK_ALIGNMENT
, 1);
1003 /* Enable depth test to avoid i965 blit path. */
1004 glEnable(GL_DEPTH_TEST
);
1006 memset(bitmap
, 0xff, sizeof(bitmap
));
1007 glBitmap(16, 16, 0, 0, 0, 0, bitmap
);
1009 glDisable(GL_DEPTH_TEST
);
1010 glPixelStorei(GL_UNPACK_ALIGNMENT
, old_unpack_alignment
);
1012 return piglit_check_gl_error(GL_NO_ERROR
);
1016 do_BlitFramebuffer(void)
1018 const GLuint fbos
[2] = { FIRST_SPARE_OBJECT
, FIRST_SPARE_OBJECT
+ 1 };
1019 const GLuint tex
[2] = { FIRST_SPARE_OBJECT
, FIRST_SPARE_OBJECT
+ 1 };
1022 /* GL_ARB_framebuffer_object and OpenGL 3.0 require that
1023 * glGenFramebuffers be used. This test really does require
1024 * GL_EXT_framebuffer_object and GL_EXT_framebuffer_blit.
1026 if (!(piglit_is_extension_supported("GL_EXT_framebuffer_object") &&
1027 piglit_is_extension_supported("GL_EXT_framebuffer_blit"))) {
1028 printf("%s requires EXT framebuffer objects.\n", __func__
);
1029 piglit_report_result(PIGLIT_SKIP
);
1032 /* Generate the texture objects that will be attached to the
1033 * framebuffer objects for the test.
1035 glBindTexture(GL_TEXTURE_2D
, tex
[0]);
1036 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0, GL_RGBA
,
1037 GL_UNSIGNED_BYTE
, NULL
);
1039 glBindTexture(GL_TEXTURE_2D
, tex
[1]);
1040 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0, GL_RGBA
,
1041 GL_UNSIGNED_BYTE
, NULL
);
1043 glBindTexture(GL_TEXTURE_2D
, 0);
1045 /* Generate the framebuffer objects. */
1046 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, fbos
[0]);
1047 glFramebufferTexture2DEXT(GL_DRAW_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
1048 GL_TEXTURE_2D
, tex
[0], 0 /* level */);
1049 if (glCheckFramebufferStatusEXT(GL_DRAW_FRAMEBUFFER
) !=
1050 GL_FRAMEBUFFER_COMPLETE
) {
1051 printf("\t%s,%d: Draw framebuffer is not complete.\n",
1052 __func__
, __LINE__
);
1056 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, fbos
[1]);
1057 glFramebufferTexture2DEXT(GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
1058 GL_TEXTURE_2D
, tex
[1], 0 /* level */);
1059 if (glCheckFramebufferStatusEXT(GL_READ_FRAMEBUFFER
) !=
1060 GL_FRAMEBUFFER_COMPLETE
) {
1061 printf("\t%s,%d: Read framebuffer is not complete.\n",
1062 __func__
, __LINE__
);
1066 /* Do the "real" test. */
1067 glBlitFramebufferEXT(0 /* srcX0 */, 0 /* srcY0 */,
1068 8 /* srcX1 */, 8 /* srcY1 */,
1069 0 /* dstX0 */, 0 /* dstY0 */,
1070 8 /* dstX1 */, 8 /* dstY1 */,
1071 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
1073 /* Final clean up. */
1074 glBindFramebufferEXT(GL_READ_FRAMEBUFFER
, piglit_winsys_fbo
);
1075 glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER
, piglit_winsys_fbo
);
1077 glDeleteTextures(ARRAY_SIZE(tex
), tex
);
1078 glDeleteFramebuffersEXT(ARRAY_SIZE(fbos
), fbos
);
1080 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1086 /* Pick a clear value that should avoid common hardware "fast clear"
1089 glClearColor(0.5, 0.7, 0.8, 0.2);
1091 glClear(GL_COLOR_BUFFER_BIT
);
1093 glClearColor(0.0, 0.0, 0.0, 0.0);
1094 return piglit_check_gl_error(GL_NO_ERROR
);
1098 do_ClearTexSubImage(void)
1100 GLuint tex
= FIRST_SPARE_OBJECT
;
1102 /* Pick a clear value that should avoid common hardware "fast clear"
1105 const GLuint clear_data
= 0xDEADBEEF;
1107 if (!piglit_is_extension_supported("GL_ARB_clear_texture")) {
1108 printf("%s requires GL_ARB_clear_texture.\n", __func__
);
1109 piglit_report_result(PIGLIT_SKIP
);
1112 glBindTexture(GL_TEXTURE_2D
, tex
);
1113 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0, GL_RGBA
,
1114 GL_UNSIGNED_INT_8_8_8_8
, NULL
);
1115 glBindTexture(GL_TEXTURE_2D
, 0);
1117 glClearTexSubImage(tex
, 0 /* level */,
1118 0 /* xoffset */, 0 /* yoffset */, 0 /* zoffset */,
1119 16 /* width */, 16 /* height */, 1 /* depth */,
1120 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
,
1123 glDeleteTextures(1, &tex
);
1125 return piglit_check_gl_error(GL_NO_ERROR
);
1129 do_CopyImageSubData(void)
1131 const GLuint tex
[2] = { FIRST_SPARE_OBJECT
, FIRST_SPARE_OBJECT
+ 1 };
1133 if (!piglit_is_extension_supported("GL_ARB_copy_image")) {
1134 printf("%s requires GL_ARB_copy_image.\n", __func__
);
1135 piglit_report_result(PIGLIT_SKIP
);
1138 glBindTexture(GL_TEXTURE_2D
, tex
[0]);
1139 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0,
1140 GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
1141 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
1143 glBindTexture(GL_TEXTURE_2D
, tex
[1]);
1144 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0,
1145 GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
1146 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
1148 glBindTexture(GL_TEXTURE_2D
, 0);
1150 glCopyImageSubData(tex
[0], GL_TEXTURE_2D
, 0 /* srcLevel */,
1151 0 /* srcX */, 0 /* srcY */, 0 /* srcZ */,
1152 tex
[1], GL_TEXTURE_2D
, 0 /* dstLevel */,
1153 0 /* dstX */, 0 /* dstY */, 0 /* dstZ */,
1154 16 /* srcWidth */, 16 /* srcHeight */,
1157 glDeleteTextures(ARRAY_SIZE(tex
), tex
);
1159 return piglit_check_gl_error(GL_NO_ERROR
);
1165 /* Set non-1.0 pixel zoom to avoid i965 blit path. */
1166 glPixelZoom(1.5f
, 1.5f
);
1168 glRasterPos2f(0.5, 0.5);
1169 glCopyPixels(0, 0, 4, 4, GL_COLOR
);
1171 glPixelZoom(1.0f
, 1.0f
);
1173 return piglit_check_gl_error(GL_NO_ERROR
);
1177 do_CopyTexSubImage2D(void)
1179 GLuint tex
= FIRST_SPARE_OBJECT
;
1181 /* Set non-1.0 pixel zoom to avoid i965 blorp path. */
1182 glPixelZoom(1.5f
, 1.5f
);
1184 glBindTexture(GL_TEXTURE_2D
, tex
);
1186 /* Pick GL_LUMINANCE8_ALPHA8 because most hardware can support it
1187 * natively, and most hardware cannot use a blit fast path from RGB or
1188 * RGBA to LA. i965 currently cannot.
1190 glTexImage2D(GL_TEXTURE_2D
, 0, GL_LUMINANCE8_ALPHA8
, 16, 16, 0,
1191 GL_LUMINANCE_ALPHA
, GL_UNSIGNED_BYTE
, NULL
);
1193 glCopyTexSubImage2D(GL_TEXTURE_2D
, 0, 0, 0, 0, 0, 16, 16);
1195 glPixelZoom(1.0f
, 1.0f
);
1197 glBindTexture(GL_TEXTURE_2D
, 0);
1198 glDeleteTextures(1, &tex
);
1200 return piglit_check_gl_error(GL_NO_ERROR
);
1206 GLuint pixels
[16 * 16];
1208 memset(pixels
, 0x81, sizeof(pixels
));
1209 glDrawPixels(16, 16, GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, pixels
);
1210 glDrawPixels(16, 16, GL_STENCIL_INDEX
, GL_UNSIGNED_BYTE
, pixels
);
1211 glDrawPixels(16, 16, GL_DEPTH_COMPONENT
, GL_UNSIGNED_INT
, pixels
);
1213 return piglit_check_gl_error(GL_NO_ERROR
);
1217 do_GenerateMipmap(void)
1219 const GLuint tex
= FIRST_SPARE_OBJECT
;
1222 if (!piglit_is_extension_supported("GL_EXT_framebuffer_object") &&
1223 !piglit_is_extension_supported("GL_ARB_framebuffer_object") &&
1224 piglit_get_gl_version() < 30) {
1225 printf("%s requires framebuffer objects.\n", __func__
);
1226 piglit_report_result(PIGLIT_SKIP
);
1229 if (glIsTexture(tex
)) {
1230 printf("\t%s,%d: %u is already a texture\n",
1231 __func__
, __LINE__
, tex
);
1235 glBindTexture(GL_TEXTURE_2D
, tex
);
1236 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0, GL_RGBA
,
1237 GL_UNSIGNED_INT_8_8_8_8
, NULL
);
1238 glGenerateMipmap(GL_TEXTURE_2D
);
1240 glBindTexture(GL_TEXTURE_2D
, 0);
1241 glDeleteTextures(1, &tex
);
1243 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1247 do_GetTexImage(void)
1249 const GLuint tex
= FIRST_SPARE_OBJECT
;
1250 const GLuint pbo
= FIRST_SPARE_OBJECT
;
1251 uint8_t data
[TEXTURE_DATA_SIZE
];
1254 if (!piglit_is_extension_supported("GL_EXT_pixel_buffer_object") &&
1255 piglit_get_gl_version() < 30) {
1256 printf("%s requires pixel buffer objects.\n", __func__
);
1257 piglit_report_result(PIGLIT_SKIP
);
1260 if (glIsTexture(tex
)) {
1261 printf("\t%s,%d: %u is already a texture\n",
1262 __func__
, __LINE__
, tex
);
1266 if (glIsBuffer(pbo
)) {
1267 printf("\t%s,%d: %u is already a buffer object\n",
1268 __func__
, __LINE__
, pbo
);
1272 /* Generate the initial texture object. The random number seed values
1273 * used are irrelevant.
1275 generate_random_data(data
, sizeof(data
), GL_PIXEL_UNPACK_BUFFER
, pbo
);
1276 glBindTexture(GL_TEXTURE_2D
, tex
);
1277 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0, GL_RGBA
,
1278 GL_UNSIGNED_BYTE
, data
);
1281 /* Generate the buffer object that will be used for the PBO download
1284 glBindBuffer(GL_PIXEL_PACK_BUFFER
, pbo
);
1285 glBufferData(GL_PIXEL_PACK_BUFFER
, sizeof(data
), NULL
, GL_STATIC_READ
);
1287 /* Do the "real" test. */
1288 glGetTexImage(GL_TEXTURE_2D
, 0 /* level */,
1289 GL_RGBA
, GL_UNSIGNED_BYTE
, BUFFER_OFFSET(0));
1291 /* Final clean up. */
1292 glBindTexture(GL_TEXTURE_2D
, 0);
1293 glDeleteTextures(1, &tex
);
1295 glBindBuffer(GL_PIXEL_PACK_BUFFER
, 0);
1296 glDeleteBuffers(1, &pbo
);
1298 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1302 do_GetTexImage_compressed(void)
1304 const GLuint tex
= FIRST_SPARE_OBJECT
;
1305 const GLenum internal_format
=
1306 piglit_is_extension_supported("GL_EXT_texture_compression_s3tc")
1307 ? GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
1308 : GL_COMPRESSED_RGBA_FXT1_3DFX
;
1310 /* DXT1 has 4x4 block size. The image will be 16x16 texels,
1311 * so that means 16 blocks. Each block is 64-bits (or 8
1312 * bytes). That's a total of 16 * 8 = 128 bytes.
1314 * FXT1 has 8x4 block size. The image will be 16x16 texels,
1315 * so that means 8 blocks. Each block is 128-bits (or 16
1316 * bytes). That's a total of 8 * 16 = 128 bytes.
1320 /* Buffer to hold the decompressed texture. */
1321 uint8_t texels
[16 * 16 * 4];
1325 /* This test requires:
1327 * GL_EXT_texture_compression_s3tc or GL_3DFX_texture_compression_FXT1
1331 * GL_ARB_texture_compression or OpenGL 1.3
1333 if (!(piglit_is_extension_supported("GL_ARB_texture_compression") ||
1334 piglit_get_gl_version() >= 13) ||
1335 !(piglit_is_extension_supported("GL_EXT_texture_compression_s3tc") ||
1336 piglit_is_extension_supported("GL_3DFX_texture_compression_FXT1"))) {
1337 printf("%s requires either S3TC or FXT1 texture compression.\n",
1339 piglit_report_result(PIGLIT_SKIP
);
1342 if (glIsTexture(tex
)) {
1343 printf("\t%s,%d: %u is already a texture\n",
1344 __func__
, __LINE__
, tex
);
1348 /* Generate the initial texture object. The random number seed values
1349 * used are irrelevant.
1351 generate_random_data(data
, sizeof(data
), GL_PIXEL_UNPACK_BUFFER
, tex
);
1352 glBindTexture(GL_TEXTURE_2D
, tex
);
1353 glCompressedTexImage2D(GL_TEXTURE_2D
, 0 /* level */, internal_format
,
1354 16 /* width */, 16 /* height */, 0 /* border */,
1355 sizeof(data
), data
);
1357 /* Do the "real" test. */
1358 glGetTexImage(GL_TEXTURE_2D
, 0 /* level */,
1359 GL_RGBA
, GL_UNSIGNED_BYTE
, texels
);
1361 /* Final clean up. */
1362 glBindTexture(GL_TEXTURE_2D
, 0);
1363 glDeleteTextures(1, &tex
);
1365 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1369 do_TexSubImage2D(void)
1371 const GLuint tex
= FIRST_SPARE_OBJECT
;
1372 const GLuint pbo
= FIRST_SPARE_OBJECT
;
1373 uint8_t data
[TEXTURE_DATA_SIZE
];
1376 if (!piglit_is_extension_supported("GL_EXT_pixel_buffer_object") &&
1377 piglit_get_gl_version() < 30) {
1378 printf("%s requires pixel buffer objects.\n", __func__
);
1379 piglit_report_result(PIGLIT_SKIP
);
1382 if (glIsTexture(tex
)) {
1383 printf("\t%s,%d: %u is already a texture\n",
1384 __func__
, __LINE__
, tex
);
1388 if (glIsBuffer(pbo
)) {
1389 printf("\t%s,%d: %u is already a buffer object\n",
1390 __func__
, __LINE__
, pbo
);
1394 /* Generate the initial texture object.
1396 * NOTE: This must occur before binding the PBO. Otherwise
1397 * the NULL texel pointer will be interpreted as a zero offset
1398 * in the buffer, and glTexImage2D will upload data from the
1399 * PBO. This is not the intent of this test.
1401 glBindTexture(GL_TEXTURE_2D
, tex
);
1402 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA8
, 16, 16, 0, GL_RGBA
,
1403 GL_UNSIGNED_INT_8_8_8_8
, NULL
);
1406 /* Generate the buffer object that will be used for the PBO upload
1409 generate_random_data(data
, sizeof(data
), GL_PIXEL_UNPACK_BUFFER
, pbo
);
1411 glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, pbo
);
1412 glBufferData(GL_PIXEL_UNPACK_BUFFER
, sizeof(data
), data
,
1415 /* Do the "real" test. */
1416 glTexSubImage2D(GL_TEXTURE_2D
, 0 /* level */,
1417 0 /* xoffset */, 0 /* yoffset */,
1418 16 /* width */, 16 /* height */,
1419 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8_REV
, BUFFER_OFFSET(0));
1421 /* Final clean up. */
1422 glBindTexture(GL_TEXTURE_2D
, 0);
1423 glDeleteTextures(1, &tex
);
1425 glBindBuffer(GL_PIXEL_UNPACK_BUFFER
, 0);
1426 glDeleteBuffers(1, &pbo
);
1428 return piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1432 static const struct operation
{
1435 } operation_table
[] = {
1436 { "glBitmap", do_Bitmap
},
1437 { "glBlitFramebuffer", do_BlitFramebuffer
},
1438 { "glClear", do_Clear
},
1439 { "glClearTexSubImage", do_ClearTexSubImage
},
1440 { "glCopyImageSubData", do_CopyImageSubData
},
1441 { "glCopyPixels", do_CopyPixels
},
1442 { "glCopyTexSubImage2D", do_CopyTexSubImage2D
},
1443 { "glDrawPixels", do_DrawPixels
},
1444 { "glGenerateMipmap", do_GenerateMipmap
},
1445 { "glGetTexImage", do_GetTexImage
},
1446 { "glGetTexImage-compressed", do_GetTexImage_compressed
},
1447 { "glTexSubImage2D", do_TexSubImage2D
},
1450 static const struct object_type
{
1452 bool (*create
)(unsigned name
);
1453 bool (*validate
)(unsigned name
);
1454 } object_type_table
[] = {
1455 { "buffer", create_buffer
, validate_buffer
},
1456 { "framebuffer", create_framebuffer
, validate_framebuffer
},
1457 { "program", create_program
, validate_program
},
1458 { "renderbuffer", create_renderbuffer
, validate_renderbuffer
},
1459 { "texture", create_texture
, validate_texture
},
1460 { "vertex-array", create_vertex_array
, validate_vertex_array
},
1463 static NORETURN
void
1464 usage(const char *prog
)
1469 printf("\t%s operation object-type\n\n", prog
);
1470 printf("Where operation is one of:\n");
1472 for (i
= 0; i
< ARRAY_SIZE(operation_table
); i
++)
1473 printf("\t%s\n", operation_table
[i
].name
);
1475 printf("\nAnd object-type is one of:\n");
1477 for (i
= 0; i
< ARRAY_SIZE(object_type_table
); i
++)
1478 printf("\t%s\n", object_type_table
[i
].name
);
1480 piglit_report_result(PIGLIT_FAIL
);
1484 piglit_init(int argc
, char **argv
)
1488 const struct object_type
*object_type
= NULL
;
1489 const struct operation
*operation
= NULL
;
1490 unsigned first_unused_texture
;
1491 unsigned first_unused_framebuffer
;
1496 for (i
= 0; i
< ARRAY_SIZE(operation_table
); i
++) {
1497 if (strcmp(argv
[1], operation_table
[i
].name
) == 0) {
1498 operation
= &operation_table
[i
];
1503 if (operation
== NULL
)
1506 for (i
= 0; i
< ARRAY_SIZE(object_type_table
); i
++) {
1507 if (strcmp(argv
[2], object_type_table
[i
].name
) == 0) {
1508 object_type
= &object_type_table
[i
];
1513 if (object_type
== NULL
)
1516 printf("Test case %s with %s\n", object_type
->name
, operation
->name
);
1518 /* This is a bit ugly, but it is necessary. When a test is run with
1519 * -fbo, the piglit framework will create some textures before calling
1520 * piglit_init. These textures will likely have names that conflict
1521 * with the names that are used by this test, so the test should avoid
1524 * HOWEVER, the test should only avoid lower numbered textures. If
1525 * the piglit framework created a texture named 1, the test should
1526 * still try to use a buffer object named 1.
1528 for (first_unused_texture
= 1;
1529 first_unused_texture
< 16;
1530 first_unused_texture
++) {
1531 if (!glIsTexture(first_unused_texture
))
1535 if (first_unused_texture
>= 16)
1536 piglit_report_result(PIGLIT_FAIL
);
1538 for (first_unused_framebuffer
= 1;
1539 first_unused_framebuffer
< 16;
1540 first_unused_framebuffer
++) {
1541 if (!glIsFramebufferEXT(first_unused_framebuffer
))
1545 if (first_unused_framebuffer
>= 16)
1546 piglit_report_result(PIGLIT_FAIL
);
1548 pass
= operation
->func() && pass
;
1550 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1552 for (unsigned name
= 1; name
< 16; name
++) {
1553 if (strcmp("texture", object_type
->name
) == 0 &&
1554 name
< first_unused_texture
)
1557 if (strcmp("framebuffer", object_type
->name
) == 0 &&
1558 name
< first_unused_framebuffer
)
1561 pass
= object_type
->create(name
) && pass
;
1564 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1566 pass
= operation
->func() && pass
;
1568 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1570 for (unsigned name
= 1; name
< 16; name
++) {
1571 if (strcmp("texture", object_type
->name
) == 0 &&
1572 name
< first_unused_texture
)
1575 if (strcmp("framebuffer", object_type
->name
) == 0 &&
1576 name
< first_unused_framebuffer
)
1579 pass
= object_type
->validate(name
) && pass
;
1582 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
1584 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);
1588 piglit_display(void)