/* * Copyright © 2011 Intel Corporation * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice (including the next * paragraph) shall be included in all copies or substantial portions of the * Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. */ /** * \file depth-stencil-texture.c * Create a depth-stencil texture when ARB_depth_texture is not supported. * * The EXT_packed_depth_stencil spec neglects to mention an interaction * (though the header of the spec says "ARB_depth_texture affects the * definition of this extension."), but ARB_framebuffer_object, which includes * EXT_packed_depth_stencil functionality says: * * "If ARB_depth_texture or SGIX_depth_texture is supported, * GL_DEPTH_STENCIL/GL_UNSIGNED_INT_24_8 data can also be used for * textures;" * * In cases where neither ARB_depth_texture nor SGIX_depth_texture is * supported, trying to create a texture with a depth-stencil format should * generate an error. */ #include "piglit-util-gl.h" PIGLIT_GL_TEST_CONFIG_BEGIN #if defined PIGLIT_USE_OPENGL config.supports_gl_compat_version = 12; config.supports_gl_core_version = 31; #elif defined PIGLIT_USE_OPENGL_ES2 config.supports_gl_es_version = 20; #elif defined PIGLIT_USE_OPENGL_ES1 config.supports_gl_es_version = 11; #endif config.window_visual = PIGLIT_GL_VISUAL_RGBA; config.khr_no_error_support = PIGLIT_HAS_ERRORS; PIGLIT_GL_TEST_CONFIG_END static bool has_texture_3d = false; static bool has_texture_cube_map = false; static bool has_depth_texture_cube_map = false; static bool has_depth_texture = false; static bool check_gl_error2_(GLenum expected_error1, GLenum expected_error2, const char *file, unsigned line) { const GLenum actual_error = glGetError(); if (actual_error == expected_error1 || actual_error == expected_error2) { return true; } /* * If the lookup of the error's name is successful, then print * Unexpected GL error: NAME 0xHEX * Else, print * Unexpected GL error: 0xHEX */ printf("Unexpected GL error: %s 0x%x\n", piglit_get_gl_error_name(actual_error), actual_error); printf("(Error at %s:%u)\n", file, line); if (expected_error2 != GL_NO_ERROR) { printf("Expected GL error: %s 0x%x or %s 0x%x\n", piglit_get_gl_error_name(expected_error1), expected_error1, piglit_get_gl_error_name(expected_error2), expected_error2); } else if (expected_error1 != GL_NO_ERROR) { printf("Expected GL error: %s 0x%x\n", piglit_get_gl_error_name(expected_error1), expected_error1); } return false; } #define check_gl_error2(a, b) check_gl_error2_(a, b, __FILE__, __LINE__) static bool try_TexImage(GLenum internalFormat) { bool pass = true; GLuint tex[4]; GLenum expected_error = has_depth_texture ? GL_NO_ERROR : GL_INVALID_VALUE; GLenum alt_error = GL_NO_ERROR; GLenum expected_3D_error = has_depth_texture ? GL_INVALID_OPERATION : GL_INVALID_VALUE; GLenum alt_3D_error = GL_NO_ERROR; GLenum expected_cube_error = has_depth_texture_cube_map ? GL_NO_ERROR : expected_3D_error; GLenum alt_cube_error = GL_NO_ERROR; #if !defined PIGLIT_USE_OPENGL /* The OpenGL ES rules are non-obvious. * * In OpenGL ES 1.x and 2.x, the internal format and the format must * be the same. This even applies in OpenGL ES 2.0 when * GL_OES_depth_texture is available. * * Section 3.7.1 (Texture Image Specification) of the OpenGL ES 1.1.12 * spec says: * * "If internalformat does not match format, the error * INVALID_OPERATION is generated." * * Section 3.7.1 (Texture Image Specification) of the OpenGL ES 2.0.25 * spec says the same thing. * * As a result, in OpenGL ES 1.x or OpenGL ES 2.0 without * GL_OES_depth_texture, glTexImage2D(..., GL_DEPTH24_STENCIL8, ..., * GL_DEPTH_STENCIL, FLOAT_32_UNSIGNED_INT_24_8) may generate *either* * GL_INVALID_VALUE or GL_INVALID_OPERATION depending on the order the * implementation checks the errors. * * In OpenGL ES 3.0, the internal format must not be GL_DEPTH_STENCIL. * Section 3.8.3 (Texture Image Specification) of the OpenGL ES 3.0.3 * spec says: * * "Specifying a combination of values for format, type, and * internalformat that is not listed as a valid combination in * tables 3.2 or 3.3 generates the error INVALID_OPERATION." * * Table 3.2 contains the lines: * * Format Type External Internal * Bytes Format * Per Pixel * DEPTH_STENCIL UNSIGNED_INT_24_8 4 DEPTH24_STENCIL8 * DEPTH_STENCIL FLOAT_32_UNSIGNED_INT_24_8 8 DEPTH32F_STENCIL8 * * The GL_OES_packed_depth_stencil spec still says: * * "Accepted by the parameter of TexImage2D and * TexSubImage2D and by the parameter of * TexImage2D: * * DEPTH_STENCIL_OES 0x84F9" * * An OpenGL ES 3.0 implementation that advertises * GL_OES_packed_depth_stencil should accepth both GL_DEPTH_STENCIL * and GL_DEPTH24_STENCIL8 for internalformat. */ if (has_depth_texture) { if ((piglit_get_gl_version() < 30 && internalFormat != GL_DEPTH_STENCIL) || (piglit_get_gl_version() >= 30 && internalFormat == GL_DEPTH_STENCIL && !piglit_is_extension_supported("GL_OES_packed_depth_stencil"))) { expected_error = GL_INVALID_OPERATION; alt_error = GL_NO_ERROR; /* 3D depth textures are never supported. * GL_INVALID_OPERATION is expected. That * error is already expected due to the * mismatch of internalformat and format. */ expected_3D_error = GL_INVALID_OPERATION; alt_3D_error = GL_NO_ERROR; /* Cube map depth textures are only supported * with GL_OES_depth_texture_cube_map. * Without that extension, * GL_INVALID_OPERATION is expected. That * error is already expected due to the * mismatch of internalformat and format. */ expected_cube_error = GL_INVALID_OPERATION; alt_cube_error = GL_NO_ERROR; } else { expected_error = GL_NO_ERROR; alt_error = GL_NO_ERROR; /* 3D depth textures are never supported. * GL_INVALID_OPERATION is expected. */ expected_3D_error = GL_INVALID_OPERATION; alt_3D_error = GL_NO_ERROR; /* Cube map depth textures are only supported * with GL_OES_depth_texture_cube_map. * Without that extension, * GL_INVALID_OPERATION is expected. */ expected_cube_error = has_depth_texture_cube_map ? GL_NO_ERROR : GL_INVALID_OPERATION; alt_cube_error = GL_NO_ERROR; } } else { assert(piglit_get_gl_version() < 30); if (internalFormat != GL_DEPTH_STENCIL) { /* For all of the cases either GL_INVALID_VALUE could * be generated due to format being GL_DEPTH_STENCIL * or GL_INVALID_OPERATION could be generated due to * format not being the same as internalformat. */ expected_error = GL_INVALID_OPERATION; alt_error = GL_INVALID_VALUE; expected_3D_error = GL_INVALID_OPERATION; alt_3D_error = GL_INVALID_VALUE; expected_cube_error = GL_INVALID_OPERATION; alt_cube_error = GL_INVALID_VALUE; } else { /* For all of these cases, GL_INVALID_VALUE is the * only acceptable error. The OpenGL ES 1.x and 2.0 * specs make no mention of generating * GL_INVALID_OPERATION for the 3D or cube map cases. */ expected_error = GL_INVALID_VALUE; alt_error = GL_NO_ERROR; expected_3D_error = GL_INVALID_VALUE; alt_3D_error = GL_NO_ERROR; expected_cube_error = GL_INVALID_VALUE; alt_cube_error = GL_NO_ERROR; } } #endif /* !defined PIGLIT_USE_OPENGL */ printf("Testing glTexImage with %s...\n", piglit_get_gl_enum_name(internalFormat)); glGenTextures(ARRAY_SIZE(tex), tex); #if defined PIGLIT_USE_OPENGL glBindTexture(GL_TEXTURE_1D, tex[0]); glTexImage1D(GL_TEXTURE_1D, 0, internalFormat, 16, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); pass = check_gl_error2(expected_error, alt_error) && pass; #endif glBindTexture(GL_TEXTURE_2D, tex[1]); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 16, 16, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); pass = check_gl_error2(expected_error, alt_error) && pass; /* Section 3.8.1 (Texture Image Specification) of the OpenGL 2.1 spec * says: * * "Textures with a base internal format of DEPTH_COMPONENT are * supported by texture image specification commands only if * target is TEXTURE_1D, TEXTURE_2D, PROXY_TEXTURE_1D or * PROXY_TEXTURE_2D. Using this format in conjunction with any * other target will result in an INVALID_OPERATION error." * * The OpenGL 4.4 spec lists the same error, but it greatly expands * the list of valid texture targets. */ #if !defined PIGLIT_USE_OPENGL_ES1 if (has_texture_3d) { glBindTexture(GL_TEXTURE_3D, tex[2]); glTexImage3D(GL_TEXTURE_3D, 0, internalFormat, 8, 8, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); pass = check_gl_error2(expected_3D_error, alt_3D_error) && pass; } #else /* Silence "variable ‘expected_3D_error’ set but not used" warnings. */ (void) expected_3D_error; (void) alt_3D_error; #endif if (has_texture_cube_map) { unsigned i; glBindTexture(GL_TEXTURE_CUBE_MAP, tex[3]); for (i = 0; i < 6; i++) { glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, internalFormat, 16, 16, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL); pass = check_gl_error2(expected_cube_error, alt_cube_error) && pass; } } #if defined PIGLIT_USE_OPENGL glBindTexture(GL_TEXTURE_1D, 0); #endif glBindTexture(GL_TEXTURE_2D, 0); if (has_texture_3d) glBindTexture(GL_TEXTURE_3D, 0); if (has_texture_cube_map) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glDeleteTextures(ARRAY_SIZE(tex), tex); printf("Done.\n\n"); return pass; } #if !defined PIGLIT_USE_OPENGL_ES1 static bool try_TexStorage(GLenum internalFormat) { bool pass = true; GLuint tex[4]; GLenum expected_error; GLenum expected_3D_error; GLenum expected_cube_error; /* The GL_ARB_texture_storage spec says: * * "- If is one of the internal formats listed in * table 3.11, an INVALID_ENUM error is generated." * * Table 3.11 lists the unsized formats, including GL_DEPTH_STENCIL. */ if (internalFormat == GL_DEPTH_STENCIL) { expected_error = has_depth_texture ? GL_INVALID_ENUM : GL_INVALID_VALUE; expected_3D_error = has_depth_texture ? GL_INVALID_ENUM : GL_INVALID_VALUE; expected_cube_error = has_depth_texture_cube_map ? GL_INVALID_ENUM : GL_INVALID_VALUE; } else { expected_error = has_depth_texture ? GL_NO_ERROR : GL_INVALID_VALUE; expected_3D_error = has_depth_texture ? GL_INVALID_OPERATION : GL_INVALID_VALUE; expected_cube_error = has_depth_texture_cube_map ? GL_NO_ERROR : expected_3D_error; } printf("Testing glTexStorage with %s...\n", piglit_get_gl_enum_name(internalFormat)); glGenTextures(ARRAY_SIZE(tex), tex); #if defined PIGLIT_USE_OPENGL glBindTexture(GL_TEXTURE_1D, tex[0]); glTexStorage1D(GL_TEXTURE_1D, 1, internalFormat, 16); pass = piglit_check_gl_error(expected_error) && pass; #endif glBindTexture(GL_TEXTURE_2D, tex[1]); glTexStorage2D(GL_TEXTURE_2D, 1, internalFormat, 16, 16); pass = piglit_check_gl_error(expected_error) && pass; #if !defined PIGLIT_USE_OPENGL_ES1 if (has_texture_3d) { glBindTexture(GL_TEXTURE_3D, tex[2]); glTexStorage3D(GL_TEXTURE_3D, 1, internalFormat, 8, 8, 8); pass = piglit_check_gl_error(expected_3D_error) && pass; } #else /* Silence "variable ‘expected_3D_error’ set but not used" warnings. */ (void) expected_3D_error; #endif if (has_texture_cube_map) { glBindTexture(GL_TEXTURE_CUBE_MAP, tex[3]); glTexStorage2D(GL_TEXTURE_CUBE_MAP, 1, internalFormat, 16, 16); pass = piglit_check_gl_error(expected_cube_error) && pass; } #if defined PIGLIT_USE_OPENGL glBindTexture(GL_TEXTURE_1D, 0); #endif glBindTexture(GL_TEXTURE_2D, 0); if (has_texture_3d) glBindTexture(GL_TEXTURE_3D, 0); if (has_texture_cube_map) glBindTexture(GL_TEXTURE_CUBE_MAP, 0); glDeleteTextures(ARRAY_SIZE(tex), tex); printf("Done.\n\n"); return pass; } #endif /* !defined PIGLIT_USE_OPENGL_ES1 */ void piglit_init(int argc, char **argv) { bool pass = true; bool has_texture_storage; #if defined PIGLIT_USE_OPENGL if (piglit_get_gl_version() < 30 && !piglit_is_extension_supported("GL_EXT_packed_depth_stencil") && !piglit_is_extension_supported("GL_ARB_framebuffer_object")) { printf("OpenGL 3.0, GL_EXT_packed_depth_stencil, or " "GL_ARB_framebuffer_object is required.\n"); piglit_report_result(PIGLIT_SKIP); } has_depth_texture = piglit_get_gl_version() >= 14 || piglit_is_extension_supported("GL_ARB_depth_texture") || piglit_is_extension_supported("GL_SGIX_depth_texture"); has_texture_3d = true; has_texture_cube_map = piglit_get_gl_version() >= 13 || piglit_is_extension_supported("GL_ARB_texture_cube_map"); has_depth_texture_cube_map = piglit_get_gl_version() >= 30 || piglit_is_extension_supported("GL_EXT_gpu_shader4"); has_texture_storage = piglit_get_gl_version() >= 42 || piglit_is_extension_supported("GL_ARB_texture_storage"); #elif defined PIGLIT_USE_OPENGL_ES2 if (piglit_get_gl_version() < 30 && !piglit_is_extension_supported("GL_OES_packed_depth_stencil")) { printf("OpenGL ES 3.0 or GL_OES_packed_depth_stencil " "is required.\n"); piglit_report_result(PIGLIT_SKIP); } has_depth_texture = piglit_get_gl_version() >= 30 || piglit_is_extension_supported("GL_OES_depth_texture"); has_texture_3d = piglit_get_gl_version() >= 30 || piglit_is_extension_supported("GL_OES_texture_3D"); has_texture_cube_map = true; has_depth_texture_cube_map = piglit_get_gl_version() >= 30 || piglit_is_extension_supported("GL_OES_depth_texture_cube_map"); has_texture_storage = piglit_get_gl_version() >= 30 || piglit_is_extension_supported("GL_EXT_texture_storage"); #elif defined PIGLIT_USE_OPENGL_ES1 piglit_require_extension("GL_OES_packed_depth_stencil"); has_depth_texture = false; has_texture_3d = false; has_texture_cube_map = piglit_is_extension_supported("GL_OES_texture_cube_map"); has_depth_texture_cube_map = false; has_texture_storage = piglit_is_extension_supported("GL_EXT_texture_storage"); #endif pass = try_TexImage(GL_DEPTH_STENCIL) && pass; pass = try_TexImage(GL_DEPTH24_STENCIL8) && pass; /* Disable this path for OpenGL ES 1.x because piglit dispatch doesn't * seem to support it yet. */ #if !defined PIGLIT_USE_OPENGL_ES1 if (has_texture_storage) { pass = try_TexStorage(GL_DEPTH_STENCIL) && pass; pass = try_TexStorage(GL_DEPTH24_STENCIL8) && pass; } #else /* Silence "variable ‘has_texture_storage’ set but not used" warnings. */ (void) has_texture_storage; #endif piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); } enum piglit_result piglit_display(void) { /* UNREACHED */ return PIGLIT_FAIL; }