2 * Copyright (c) 2011 VMware, Inc.
3 * Copyright (c) 2014 Intel Corporation
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * on the rights to use, copy, modify, merge, publish, distribute, sub
9 * license, and/or sell copies of the Software, and to permit persons to whom
10 * the Software is furnished to do so, subject to the following conditions:
12 * The above copyright notice and this permission notice (including the next
13 * paragraph) shall be included in all copies or substantial portions of the
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
20 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
21 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Note: only the glTextureStorage2D() function is tested with actual
31 #include "piglit-util-gl.h"
32 #include "dsa-utils.h"
34 PIGLIT_GL_TEST_CONFIG_BEGIN
36 config
.supports_gl_core_version
= 31;
37 config
.supports_gl_compat_version
= 20;
39 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
40 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
42 PIGLIT_GL_TEST_CONFIG_END
44 static const char *TestName
= "texture-storage";
46 static GLubyte Colors
[][4] = {
61 * Do error-check tests for a non-mipmapped texture.
64 test_one_level_errors(GLenum target
)
66 const GLint width
= 64, height
= 4, depth
= 8;
70 assert(target
== GL_TEXTURE_1D
||
71 target
== GL_TEXTURE_2D
||
72 target
== GL_TEXTURE_3D
);
74 glCreateTextures(target
, 1, &tex
);
75 glBindTextureUnit(0, tex
);
77 if (target
== GL_TEXTURE_1D
) {
78 glTextureStorage1D(tex
, 1, GL_RGBA8
, width
);
79 } else if (target
== GL_TEXTURE_2D
) {
80 glTextureStorage2D(tex
, 1, GL_RGBA8
, width
, height
);
81 } else if (target
== GL_TEXTURE_3D
) {
82 glTextureStorage3D(tex
, 1, GL_RGBA8
, width
, height
, depth
);
85 piglit_check_gl_error(GL_NO_ERROR
);
87 glGetTextureLevelParameteriv(tex
, 0, GL_TEXTURE_WIDTH
, &v
);
89 printf("%s: bad width: %d, should be %d\n", TestName
, v
, width
);
93 if (target
!= GL_TEXTURE_1D
) {
94 glGetTextureLevelParameteriv(tex
, 0, GL_TEXTURE_HEIGHT
, &v
);
96 printf("%s: bad height: %d, should be %d\n", TestName
,
102 if (target
== GL_TEXTURE_3D
) {
103 glGetTextureLevelParameteriv(tex
, 0, GL_TEXTURE_DEPTH
, &v
);
105 printf("%s: bad depth: %d, should be %d\n", TestName
,
111 /* The ARB_texture_storage spec says:
113 * "Using any of the following commands with the same texture will
114 * result in the error INVALID_OPERATION being generated, even if
115 * it does not affect the dimensions or format:
118 * - CompressedTexImage*
122 if (!piglit_khr_no_error
&& target
== GL_TEXTURE_2D
) {
123 glTexImage2D(target
, 0, GL_RGBA
, width
, height
, 0,
124 GL_RGBA
, GL_UNSIGNED_BYTE
, NULL
);
125 if (glGetError() != GL_INVALID_OPERATION
) {
126 printf("%s: glTexImage2D failed to generate error\n",
131 glTextureStorage2D(tex
, 1, GL_RGBA8
, width
, height
);
132 if (glGetError() != GL_INVALID_OPERATION
) {
133 printf("%s: glTextureStorage2D() failed to generate "
134 "error\n", TestName
);
138 glCopyTexImage2D(target
, 0, GL_RGBA
, 0, 0, width
, height
, 0);
139 if (glGetError() != GL_INVALID_OPERATION
) {
140 printf("%s: glCopyTexImage2D() failed to generate "
141 "error\n", TestName
);
146 glDeleteTextures(1, &tex
);
153 * Do error-check tests for a mipmapped texture.
156 test_mipmap_errors(GLenum target
)
158 GLint width
= 128, height
= 64, depth
= 4, levels
= 8;
159 const char *targetString
= piglit_get_gl_enum_name(target
);
163 assert(target
== GL_TEXTURE_1D
||
164 target
== GL_TEXTURE_2D
||
165 target
== GL_TEXTURE_3D
);
167 glCreateTextures(target
, 1, &tex
);
168 glBindTextureUnit(0, tex
);
170 if (target
== GL_TEXTURE_1D
) {
171 glTextureStorage1D(tex
, levels
, GL_RGBA8
, width
);
172 } else if (target
== GL_TEXTURE_2D
) {
173 glTextureStorage2D(tex
, levels
, GL_RGBA8
, width
, height
);
174 } else if (target
== GL_TEXTURE_3D
) {
175 glTextureStorage3D(tex
, levels
, GL_RGBA8
, width
,
179 piglit_check_gl_error(GL_NO_ERROR
);
181 glGetTextureParameteriv(tex
, GL_TEXTURE_IMMUTABLE_FORMAT
, &v
);
183 printf("%s: %s GL_TEXTURE_IMMUTABLE_FORMAT query returned "
185 TestName
, targetString
);
189 for (l
= 0; l
< levels
; l
++) {
190 glGetTextureLevelParameteriv(tex
, l
, GL_TEXTURE_WIDTH
, &v
);
192 printf("%s: %s level %d: bad width: %d, should be %d\n",
193 TestName
, targetString
, l
, v
, width
);
197 if (target
!= GL_TEXTURE_1D
) {
198 glGetTextureLevelParameteriv(tex
, l
,
199 GL_TEXTURE_HEIGHT
, &v
);
201 printf("%s: %s level %d: bad height: %d, "
203 TestName
, targetString
, l
, v
, height
);
208 if (target
== GL_TEXTURE_3D
) {
209 glGetTextureLevelParameteriv(tex
, l
,
210 GL_TEXTURE_DEPTH
, &v
);
212 printf("%s: %s level %d: bad depth: %d, "
214 TestName
, targetString
, l
, v
, depth
);
227 glDeleteTextures(1, &tex
);
234 test_cube_texture(void)
236 const GLint width
= 16, height
= 16;
237 const GLenum target
= GL_TEXTURE_CUBE_MAP
;
241 /* Test valid cube dimensions */
242 glCreateTextures(target
, 1, &tex
);
243 glBindTextureUnit(0, tex
);
244 glTextureStorage2D(tex
, 1, GL_RGBA8
, width
, height
);
245 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
246 glDeleteTextures(1, &tex
);
248 /* Test invalid cube dimensions */
249 if (!piglit_khr_no_error
) {
250 glCreateTextures(target
, 1, &tex
);
251 glBindTextureUnit(0, tex
);
252 glTextureStorage2D(tex
, 1, GL_RGBA8
, width
, height
+2);
253 pass
= piglit_check_gl_error(GL_INVALID_VALUE
) && pass
;
254 glDeleteTextures(1, &tex
);
262 test_cube_array_texture(void)
264 const GLint width
= 16, height
= 16;
265 const GLenum target
= GL_TEXTURE_CUBE_MAP_ARRAY
;
269 /* Test valid cube array dimensions */
270 glCreateTextures(target
, 1, &tex
);
271 glBindTextureUnit(0, tex
);
272 glTextureStorage3D(tex
, 1, GL_RGBA8
, width
, height
, 12);
273 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
274 glDeleteTextures(1, &tex
);
276 if (!piglit_khr_no_error
) {
277 /* Test invalid cube array width, height dimensions */
278 glCreateTextures(target
, 1, &tex
);
279 glBindTextureUnit(0, tex
);
280 glTextureStorage3D(tex
, 1, GL_RGBA8
, width
, height
+3, 12);
281 pass
= piglit_check_gl_error(GL_INVALID_VALUE
) && pass
;
282 glDeleteTextures(1, &tex
);
284 /* Test invalid cube array depth */
285 glCreateTextures(target
, 1, &tex
);
286 glBindTextureUnit(0, tex
);
287 glTextureStorage3D(tex
, 1, GL_RGBA8
, width
, height
, 12+2);
288 pass
= piglit_check_gl_error(GL_INVALID_VALUE
) && pass
;
289 glDeleteTextures(1, &tex
);
297 * Create a single-color image.
300 create_image(GLint w
, GLint h
, const GLubyte color
[4])
302 GLubyte
*buf
= (GLubyte
*) malloc(w
* h
* 4);
304 for (i
= 0; i
< w
* h
; i
++) {
305 buf
[i
*4+0] = color
[0];
306 buf
[i
*4+1] = color
[1];
307 buf
[i
*4+2] = color
[2];
308 buf
[i
*4+3] = color
[3];
315 * Test a mip-mapped texture w/ rendering.
318 test_2d_mipmap_rendering(void)
321 GLint width
= 128, height
= 64, levels
= 8;
326 glCreateTextures(GL_TEXTURE_2D
, 1, &tex
);
327 glBindTextureUnit(0, tex
);
329 glTextureStorage2D(tex
, levels
, GL_RGBA8
, width
, height
);
331 piglit_check_gl_error(GL_NO_ERROR
);
333 /* check that the mipmap level sizes are correct */
334 for (l
= 0; l
< levels
; l
++) {
335 GLubyte
*buf
= create_image(width
, height
, Colors
[l
]);
337 glTextureSubImage2D(tex
, l
, 0, 0, width
, height
,
338 GL_RGBA
, GL_UNSIGNED_BYTE
, buf
);
342 glGetTextureLevelParameteriv(tex
, l
, GL_TEXTURE_WIDTH
,
345 printf("%s: level %d: bad width: %d, should be %d\n",
346 TestName
, l
, v
, width
);
350 glGetTextureLevelParameteriv(tex
, l
, GL_TEXTURE_HEIGHT
,
353 printf("%s: level %d: bad height: %d, should be %d\n",
354 TestName
, l
, v
, height
);
359 /* Added to test glGetTextureLevelParameterfv */
360 glGetTextureLevelParameterfv(tex
, l
, GL_TEXTURE_WIDTH
,
362 if (vfloat
!= (GLfloat
) width
) {
363 printf("%s: level %d: bad width: %.2f, "
365 TestName
, l
, vfloat
, (GLfloat
) width
);
369 glGetTextureLevelParameterfv(tex
, l
, GL_TEXTURE_HEIGHT
,
371 if (vfloat
!= (GLfloat
) height
) {
372 printf("%s: level %d: bad height: %.2f, "
374 TestName
, l
, vfloat
, (GLfloat
) height
);
385 /* This should generate and error (bad level) */
386 if (!piglit_khr_no_error
) {
387 GLubyte
*buf
= create_image(width
, height
, Colors
[l
]);
390 glTextureSubImage2D(tex
, levels
, 0, 0, width
, height
,
391 GL_RGBA
, GL_UNSIGNED_BYTE
, buf
);
394 if (err
== GL_NO_ERROR
) {
395 printf("%s: glTextureSubImage2D(illegal level)"
396 " failed to generate an error.\n",
404 /* now do a rendering test */
405 glTextureParameteri(tex
, GL_TEXTURE_MIN_FILTER
,
406 GL_NEAREST_MIPMAP_NEAREST
);
407 glTextureParameteri(tex
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
409 prog
= dsa_create_program(GL_TEXTURE_2D
);
412 /* draw a quad using each texture mipmap level */
413 for (l
= 0; l
< levels
; l
++) {
417 glTextureParameteri(tex
, GL_TEXTURE_BASE_LEVEL
, l
);
418 glTextureParameteri(tex
, GL_TEXTURE_MAX_LEVEL
, l
);
420 glClear(GL_COLOR_BUFFER_BIT
);
422 piglit_draw_rect_tex(-1.0, -1.0, 2.0, 2.0,
425 expected
[0] = Colors
[l
][0] / 255.0;
426 expected
[1] = Colors
[l
][1] / 255.0;
427 expected
[2] = Colors
[l
][2] / 255.0;
428 expected
[3] = Colors
[l
][3] / 255.0;
430 p
= piglit_probe_pixel_rgb(piglit_width
/2, piglit_height
/2,
433 piglit_present_results();
436 printf("%s: wrong color for mipmap level %d\n",
443 glDeleteProgram(prog
);
445 glDeleteTextures(1, &tex
);
452 * Per issue 27 of the spec, only sized internalFormat values are allowed.
453 * Ex: GL_RGBA8 is OK but GL_RGBA is illegal.
454 * Check some common formats here. These lists aren't exhaustive since
455 * there are many extensions/versions that could effect the lists (ex:
456 * integer formats, etc.)
459 test_internal_formats(void)
461 const GLenum target
= GL_TEXTURE_2D
;
462 static const GLenum legal_formats
[] = {
469 GL_DEPTH_COMPONENT16
,
472 static const GLenum illegal_formats
[] = {
481 GL_COMPRESSED_LUMINANCE_ALPHA
,
482 GL_COMPRESSED_LUMINANCE
,
483 GL_COMPRESSED_INTENSITY
,
488 GL_COMPRESSED_SRGB_ALPHA
,
489 GL_COMPRESSED_SLUMINANCE
,
490 GL_COMPRESSED_SLUMINANCE_ALPHA
496 for (i
= 0; i
< ARRAY_SIZE(legal_formats
); i
++) {
497 glCreateTextures(target
, 1, &tex
);
498 glBindTextureUnit(0, tex
);
500 glTextureStorage2D(tex
, 1, legal_formats
[i
], 32, 32);
502 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
503 printf("%s: internal format %s should be legal"
504 " but raised an error.",
506 piglit_get_gl_enum_name(legal_formats
[i
]));
510 glDeleteTextures(1, &tex
);
513 /* Return early if KHR_no_error is enabled */
514 if (piglit_khr_no_error
)
517 for (i
= 0; i
< ARRAY_SIZE(illegal_formats
); i
++) {
518 glCreateTextures(target
, 1, &tex
);
519 glBindTextureUnit(0, tex
);
521 glTextureStorage2D(tex
, 1, illegal_formats
[i
], 32, 32);
523 if (!piglit_check_gl_error(GL_INVALID_ENUM
)) {
524 printf("%s: internal format %s should be illegal"
525 " but didn't raised an error.",
527 piglit_get_gl_enum_name(illegal_formats
[i
]));
531 glDeleteTextures(1, &tex
);
538 test_immutablity(GLenum target
)
542 GLint immutable_format
;
546 glCreateTextures(target
, 1, &tex
);
547 glBindTextureUnit(0, tex
);
549 glTextureStorage2D(tex
, 3, GL_RGBA8
, 256, 256);
550 glTextureParameteri(tex
, GL_TEXTURE_MAX_LEVEL
, 4);
551 glGetTextureParameteriv(tex
, GL_TEXTURE_MAX_LEVEL
, &level
);
552 glGetTextureParameteriv(tex
, GL_TEXTURE_IMMUTABLE_FORMAT
,
555 if (immutable_format
!= GL_TRUE
) {
556 printf("%s: GL_TEXTURE_IMMUTABLE_FORMAT was not set to "
557 "GL_TRUE after glTextureStorage2D\n", TestName
);
561 /* The ARB_texture_storage spec says:
563 * "However, if TEXTURE_IMMUTABLE_FORMAT is TRUE, then
564 * level_base is clamped to the range [0, <levels> - 1]
565 * and level_max is then clamped to the range [level_base,
566 * <levels> - 1], where <levels> is the parameter passed
567 * the call to TexStorage* for the texture object"
569 printf("%s: GL_TEXTURE_MAX_LEVEL changed to %d, which is "
570 "outside the clamp range for immutables\n",
575 /* Other immutable tests happen per-format above */
577 glDeleteTextures(1, &tex
);
583 const bool subtest_pass = (f); \
584 piglit_report_subtest_result(subtest_pass \
585 ? PIGLIT_PASS : PIGLIT_FAIL, \
587 pass = pass && subtest_pass; \
595 X(test_one_level_errors(GL_TEXTURE_1D
), "1D non-mipmapped");
596 X(test_one_level_errors(GL_TEXTURE_2D
), "2D non-mipmapped");
597 X(test_one_level_errors(GL_TEXTURE_3D
), "3D non-mipmapped");
598 X(test_mipmap_errors(GL_TEXTURE_1D
), "1D mipmapped");
599 X(test_mipmap_errors(GL_TEXTURE_2D
), "2D mipmapped");
600 X(test_mipmap_errors(GL_TEXTURE_3D
), "3D mipmapped");
601 X(test_2d_mipmap_rendering(), "2D mipmap rendering");
602 X(test_internal_formats(), "internal formats");
603 X(test_immutablity(GL_TEXTURE_2D
), "immutability");
604 X(test_cube_texture(), "cube texture");
606 if (piglit_is_extension_supported("GL_ARB_texture_cube_map_array"))
607 X(test_cube_array_texture(), "cube array texture");
609 piglit_report_subtest_result(PIGLIT_SKIP
,
610 "cube array texture");
612 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
617 piglit_init(int argc
, char **argv
)
619 piglit_require_extension("GL_ARB_texture_storage");
620 piglit_require_extension("GL_ARB_direct_state_access");