fbo-mrt-alphatest: Actually require MRTs to be available.
[piglit.git] / tests / spec / arb_direct_state_access / texture-storage.c
blob264e7ffe6e7ce05b856f69665386b2b4e0ca2c6b
1 /*
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
14 * Software.
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
23 * SOFTWARE.
26 /**
27 * Note: only the glTextureStorage2D() function is tested with actual
28 * rendering.
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] = {
47 {255, 0, 0, 255},
48 { 0, 255, 0, 255},
49 { 0, 0, 255, 255},
50 { 0, 255, 255, 255},
51 {255, 0, 255, 255},
52 {255, 255, 0, 255},
53 {255, 255, 255, 255},
54 {128, 0, 0, 255},
55 { 0, 128, 0, 255},
56 { 0, 0, 128, 255}
60 /**
61 * Do error-check tests for a non-mipmapped texture.
63 static bool
64 test_one_level_errors(GLenum target)
66 const GLint width = 64, height = 4, depth = 8;
67 GLuint tex;
68 GLint v;
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);
88 if (v != width) {
89 printf("%s: bad width: %d, should be %d\n", TestName, v, width);
90 return false;
93 if (target != GL_TEXTURE_1D) {
94 glGetTextureLevelParameteriv(tex, 0, GL_TEXTURE_HEIGHT, &v);
95 if (v != height) {
96 printf("%s: bad height: %d, should be %d\n", TestName,
97 v, height);
98 return false;
102 if (target == GL_TEXTURE_3D) {
103 glGetTextureLevelParameteriv(tex, 0, GL_TEXTURE_DEPTH, &v);
104 if (v != depth) {
105 printf("%s: bad depth: %d, should be %d\n", TestName,
106 v, depth);
107 return false;
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:
117 * - TexImage*
118 * - CompressedTexImage*
119 * - CopyTexImage*
120 * - TexStorage*"
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",
127 TestName);
128 return false;
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);
135 return false;
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);
142 return false;
146 glDeleteTextures(1, &tex);
148 return true;
153 * Do error-check tests for a mipmapped texture.
155 static bool
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);
160 GLuint tex;
161 GLint v, l;
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,
176 height, depth);
179 piglit_check_gl_error(GL_NO_ERROR);
181 glGetTextureParameteriv(tex, GL_TEXTURE_IMMUTABLE_FORMAT, &v);
182 if (!v) {
183 printf("%s: %s GL_TEXTURE_IMMUTABLE_FORMAT query returned "
184 "false\n",
185 TestName, targetString);
186 return false;
189 for (l = 0; l < levels; l++) {
190 glGetTextureLevelParameteriv(tex, l, GL_TEXTURE_WIDTH, &v);
191 if (v != width) {
192 printf("%s: %s level %d: bad width: %d, should be %d\n",
193 TestName, targetString, l, v, width);
194 return false;
197 if (target != GL_TEXTURE_1D) {
198 glGetTextureLevelParameteriv(tex, l,
199 GL_TEXTURE_HEIGHT, &v);
200 if (v != height) {
201 printf("%s: %s level %d: bad height: %d, "
202 "should be %d\n",
203 TestName, targetString, l, v, height);
204 return false;
208 if (target == GL_TEXTURE_3D) {
209 glGetTextureLevelParameteriv(tex, l,
210 GL_TEXTURE_DEPTH, &v);
211 if (v != depth) {
212 printf("%s: %s level %d: bad depth: %d, "
213 "should be %d\n",
214 TestName, targetString, l, v, depth);
215 return false;
219 if (width > 1)
220 width /= 2;
221 if (height > 1)
222 height /= 2;
223 if (depth > 1)
224 depth /= 2;
227 glDeleteTextures(1, &tex);
229 return true;
233 static bool
234 test_cube_texture(void)
236 const GLint width = 16, height = 16;
237 const GLenum target = GL_TEXTURE_CUBE_MAP;
238 GLuint tex;
239 bool pass = true;
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);
257 return pass;
261 static bool
262 test_cube_array_texture(void)
264 const GLint width = 16, height = 16;
265 const GLenum target = GL_TEXTURE_CUBE_MAP_ARRAY;
266 GLuint tex;
267 bool pass = true;
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);
292 return pass;
297 * Create a single-color image.
299 static GLubyte *
300 create_image(GLint w, GLint h, const GLubyte color[4])
302 GLubyte *buf = (GLubyte *) malloc(w * h * 4);
303 int i;
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];
310 return buf;
315 * Test a mip-mapped texture w/ rendering.
317 static bool
318 test_2d_mipmap_rendering(void)
320 GLuint tex;
321 GLint width = 128, height = 64, levels = 8;
322 GLint v, l;
323 GLfloat vfloat;
324 GLuint prog;
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);
340 free(buf);
342 glGetTextureLevelParameteriv(tex, l, GL_TEXTURE_WIDTH,
343 &v);
344 if (v != width) {
345 printf("%s: level %d: bad width: %d, should be %d\n",
346 TestName, l, v, width);
347 return false;
350 glGetTextureLevelParameteriv(tex, l, GL_TEXTURE_HEIGHT,
351 &v);
352 if (v != height) {
353 printf("%s: level %d: bad height: %d, should be %d\n",
354 TestName, l, v, height);
355 return false;
359 /* Added to test glGetTextureLevelParameterfv */
360 glGetTextureLevelParameterfv(tex, l, GL_TEXTURE_WIDTH,
361 &vfloat);
362 if (vfloat != (GLfloat) width) {
363 printf("%s: level %d: bad width: %.2f, "
364 "should be %.2f\n",
365 TestName, l, vfloat, (GLfloat) width);
366 return false;
369 glGetTextureLevelParameterfv(tex, l, GL_TEXTURE_HEIGHT,
370 &vfloat);
371 if (vfloat != (GLfloat) height) {
372 printf("%s: level %d: bad height: %.2f, "
373 "should be %.2f\n",
374 TestName, l, vfloat, (GLfloat) height);
375 return false;
379 if (width > 1)
380 width /= 2;
381 if (height > 1)
382 height /= 2;
385 /* This should generate and error (bad level) */
386 if (!piglit_khr_no_error) {
387 GLubyte *buf = create_image(width, height, Colors[l]);
388 GLenum err;
390 glTextureSubImage2D(tex, levels, 0, 0, width, height,
391 GL_RGBA, GL_UNSIGNED_BYTE, buf);
393 err = glGetError();
394 if (err == GL_NO_ERROR) {
395 printf("%s: glTextureSubImage2D(illegal level)"
396 " failed to generate an error.\n",
397 TestName);
398 return false;
401 free(buf);
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);
410 glUseProgram(prog);
412 /* draw a quad using each texture mipmap level */
413 for (l = 0; l < levels; l++) {
414 GLfloat expected[4];
415 GLint p;
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,
423 0.0, 0.0, 1.0, 1.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,
431 expected);
433 piglit_present_results();
435 if (!p) {
436 printf("%s: wrong color for mipmap level %d\n",
437 TestName, l);
438 return false;
442 glUseProgram(0);
443 glDeleteProgram(prog);
445 glDeleteTextures(1, &tex);
447 return true;
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.)
458 static bool
459 test_internal_formats(void)
461 const GLenum target = GL_TEXTURE_2D;
462 static const GLenum legal_formats[] = {
463 GL_RGB4,
464 GL_RGB5,
465 GL_RGB8,
466 GL_RGBA2,
467 GL_RGBA4,
468 GL_RGBA8,
469 GL_DEPTH_COMPONENT16,
470 GL_DEPTH_COMPONENT32
472 static const GLenum illegal_formats[] = {
473 GL_ALPHA,
474 GL_LUMINANCE,
475 GL_LUMINANCE_ALPHA,
476 GL_INTENSITY,
477 GL_RGB,
478 GL_RGBA,
479 GL_DEPTH_COMPONENT,
480 GL_COMPRESSED_ALPHA,
481 GL_COMPRESSED_LUMINANCE_ALPHA,
482 GL_COMPRESSED_LUMINANCE,
483 GL_COMPRESSED_INTENSITY,
484 GL_COMPRESSED_RGB,
485 GL_COMPRESSED_RGBA,
486 GL_COMPRESSED_RGBA,
487 GL_COMPRESSED_SRGB,
488 GL_COMPRESSED_SRGB_ALPHA,
489 GL_COMPRESSED_SLUMINANCE,
490 GL_COMPRESSED_SLUMINANCE_ALPHA
492 GLuint tex;
493 bool pass = true;
494 int i;
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.",
505 TestName,
506 piglit_get_gl_enum_name(legal_formats[i]));
507 pass = false;
510 glDeleteTextures(1, &tex);
513 /* Return early if KHR_no_error is enabled */
514 if (piglit_khr_no_error)
515 return pass;
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.",
526 TestName,
527 piglit_get_gl_enum_name(illegal_formats[i]));
528 pass = false;
531 glDeleteTextures(1, &tex);
534 return pass;
537 static bool
538 test_immutablity(GLenum target)
540 GLuint tex;
541 GLint level;
542 GLint immutable_format;
544 bool pass = true;
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,
553 &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);
558 pass = false;
560 if (level != 2) {
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",
571 TestName, level);
572 pass = false;
575 /* Other immutable tests happen per-format above */
577 glDeleteTextures(1, &tex);
578 return pass;
581 #define X(f, n) \
582 do { \
583 const bool subtest_pass = (f); \
584 piglit_report_subtest_result(subtest_pass \
585 ? PIGLIT_PASS : PIGLIT_FAIL, \
586 (n)); \
587 pass = pass && subtest_pass; \
588 } while (0)
590 enum piglit_result
591 piglit_display(void)
593 bool pass = true;
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");
608 else
609 piglit_report_subtest_result(PIGLIT_SKIP,
610 "cube array texture");
612 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
616 void
617 piglit_init(int argc, char **argv)
619 piglit_require_extension("GL_ARB_texture_storage");
620 piglit_require_extension("GL_ARB_direct_state_access");