/* * 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 internal-format-query.c * Check that only general-purpose fmts are listed by COMPRESSED_TEXTURE_FORMATS * * From page 117 (page 129 of the PDF) of the OpenGL 1.3 spec says: * * "The set of specific compressed internal formats supported by the * renderer can be obtained by querying the value of COMPRESSED TEXTURE * FORMATS. The only values returned by this query are those corresponding * to formats suitable for general-purpose usage. The renderer will not * enumerate formats with restrictions that need to be specifically * understood prior to use." * * All texture compression extensions have taken this to mean only linear RGB * and linear RGBA formats should be exposed. */ #include "piglit-util-gl.h" PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 10; config.window_width = 10; config.window_height = 10; config.window_visual = PIGLIT_GL_VISUAL_RGB; PIGLIT_GL_TEST_CONFIG_END /** * Set of formats for a particular extension * * Each array of "good" formats and "bad" formats is terminated by a sentinel * with \c format set to zero. * * \note * The arrays are sized for the largest set from any extension. They may need * to be expanded in the future. */ struct format_list { /** * Formats that are part of the extension and should be exposed. */ GLenum good[11]; /** * Formats that are part of the extension but should not be exposed. */ GLenum bad[29]; }; /** * Formats belonging to GL_ARB_texture_comrpession_bptc * * The extension spec says nothing about whether or not these must be * advertised via GL_COMPRESSED_TEXTURE_FORMATS. The OpenGL 4.2 spec also * requires these formats, but it says that GL_NUM_COMPRESSED_TEXTURE_FORMATS * must be at least 0. NVIDIA's driver does not expose them, so we'll * classify them as optional. */ static const struct format_list bptc_formats = { { GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, 0, }, { 0, } }; /** * Formats belonging to GL_ARB_texture_comrpession_rgtc */ static const struct format_list rgtc_formats = { { 0, }, { GL_COMPRESSED_RED_RGTC1, GL_COMPRESSED_SIGNED_RED_RGTC1, GL_COMPRESSED_RG_RGTC2, GL_COMPRESSED_SIGNED_RG_RGTC2, 0, } }; /** * Formats belonging to GL_3DFX_texture_comrpession_FXT1 */ static const struct format_list fxt1_formats = { { GL_COMPRESSED_RGB_FXT1_3DFX, GL_COMPRESSED_RGBA_FXT1_3DFX, 0, }, { 0, } }; /** * Formats belonging to GL_ATI_texture_comrpession_3dc */ static const struct format_list ati_3dc_formats = { { 0, }, { GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0, } }; /** * Formats belonging to GL_EXT_texture_comrpession_latc */ static const struct format_list latc_formats = { { 0, }, { GL_COMPRESSED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT, GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT, GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT, 0, } }; /** * Formats belonging to GL_EXT_texture_comrpession_s3tc */ static const struct format_list s3tc_formats = { { GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 0, }, { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 0, } }; /** * Formats belonging to GL_EXT_texture_sRGB * * These should only be exported if GL_EXT_texture_compression_s3tc is also * supported. */ static const struct format_list srgb_formats = { { 0, }, { GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0, } }; /** * Formats belonging to GL_OES_comrpessed_paletted_texture */ static const struct format_list paletted_formats = { { GL_PALETTE4_RGB8_OES, GL_PALETTE4_RGBA8_OES, GL_PALETTE4_R5_G6_B5_OES, GL_PALETTE4_RGBA4_OES, GL_PALETTE4_RGB5_A1_OES, GL_PALETTE8_RGB8_OES, GL_PALETTE8_RGBA8_OES, GL_PALETTE8_R5_G6_B5_OES, GL_PALETTE8_RGBA4_OES, GL_PALETTE8_RGB5_A1_OES, 0, }, { 0, } }; /** * Format belonging to GL_OES_compressed_ETC1_RGB8_texture. * * The GL_OES_compressed_ETC1_RGB8_texture spec says: * * "New State * * The queries for NUM_COMPRESSED_TEXTURE_FORMATS and * COMPRESSED_TEXTURE_FORMATS include ETC1_RGB8_OES." */ static const struct format_list etc1_formats = { { GL_ETC1_RGB8_OES, 0, }, { 0, } }; /** * Formats belonging to OpenGL ES 3.0 * * These formats are dragged into desktop OpenGL via GL_ARB_ES3_compatibility * or OpenGL 4.3. The extension spec says nothing about whether or not these * must be advertised via GL_COMPRESSED_TEXTURE_FORMATS. The OpenGL 4.3 spec * requires these formats, but it says that GL_NUM_COMPRESSED_TEXTURE_FORMATS * must be at least 0. NVIDIA's driver exposes them, so we'll classify them * as optional. */ static const struct format_list etc2_formats = { { GL_COMPRESSED_RGB8_ETC2, GL_COMPRESSED_SRGB8_ETC2, GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, GL_COMPRESSED_RGBA8_ETC2_EAC, GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, GL_COMPRESSED_R11_EAC, GL_COMPRESSED_SIGNED_R11_EAC, GL_COMPRESSED_RG11_EAC, GL_COMPRESSED_SIGNED_RG11_EAC, 0, }, { 0, } }; /** * Formats belonging to GL_KHR_texture_compression_astc_ldr */ static const struct format_list astc_formats = { { 0, }, { GL_COMPRESSED_RGBA_ASTC_4x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x4_KHR, GL_COMPRESSED_RGBA_ASTC_5x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x5_KHR, GL_COMPRESSED_RGBA_ASTC_6x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x5_KHR, GL_COMPRESSED_RGBA_ASTC_8x6_KHR, GL_COMPRESSED_RGBA_ASTC_8x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x5_KHR, GL_COMPRESSED_RGBA_ASTC_10x6_KHR, GL_COMPRESSED_RGBA_ASTC_10x8_KHR, GL_COMPRESSED_RGBA_ASTC_10x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x10_KHR, GL_COMPRESSED_RGBA_ASTC_12x12_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR, GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR, 0, } }; /** * List of all known compression methods to test * * The dummy first element is because this list is used by \c main to replace * the \c argv vector when no command line parameters are supplied. */ const char *all_formats[] = { "argv[0]", "bptc", "s3tc", "fxt1", "latc", "3dc", "rgtc", "srgb", "paletted", "etc1", "etc2", "astc", }; enum piglit_result piglit_display(void) { return PIGLIT_FAIL; } static bool reject_bad(const GLenum *bad, GLenum *compressed_formats, GLint num_compressed_formats, bool check_errors) { bool pass = true; unsigned i; unsigned j; for (i = 0; bad[i] != 0; i++) { for (j = 0; j < num_compressed_formats; j++) { if (compressed_formats[j] == 0) continue; if (compressed_formats[j] == bad[i]) break; } if (j != num_compressed_formats) { if (check_errors) { fprintf(stderr, "%s should not be available.\n", piglit_get_gl_enum_name( bad[i])); pass = false; } /* Replace formats that have been processed with * zero. This allows detection of values that don't * belong to any compression extension. */ compressed_formats[j] = 0; } } return pass; } static bool try_formats(const struct format_list *t, GLenum *compressed_formats, GLint num_compressed_formats, bool check_errors, bool supported, bool optional) { bool pass = true; if (!supported) { pass = reject_bad(t->good, compressed_formats, num_compressed_formats, check_errors) && pass; } else { unsigned i; unsigned j; for (i = 0; t->good[i] != 0; i++) { for (j = 0; j < num_compressed_formats; j++) { if (compressed_formats[j] == 0) continue; if (compressed_formats[j] == t->good[i]) break; } if (j == num_compressed_formats) { if (check_errors && !optional) { fprintf(stderr, "%s should be available.\n", piglit_get_gl_enum_name( t->good[i])); pass = false; } } else { /* Replace formats that have been processed * with zero. This allows detection of values * that don't belong to any compression * extension. */ compressed_formats[j] = 0; } } } pass = reject_bad(t->bad, compressed_formats, num_compressed_formats, check_errors) && pass; return pass; } static bool test_hint(void) { GLint hint = 0; glGetIntegerv(GL_TEXTURE_COMPRESSION_HINT, &hint); if (hint != GL_DONT_CARE) { printf("Unexpected default GL_TEXTURE_COMPRESSION_HINT" " value: %s\n", piglit_get_gl_enum_name(hint)); return false; } glHint(GL_TEXTURE_COMPRESSION_HINT, GL_NICEST); glGetIntegerv(GL_TEXTURE_COMPRESSION_HINT, &hint); if (hint != GL_NICEST) { printf("Unexpected GL_TEXTURE_COMPRESSION_HINT" " value: %s\n", piglit_get_gl_enum_name(hint)); return false; } return true; } void piglit_init(int argc, char **argv) { GLint num_compressed_formats; GLenum *compressed_formats = NULL; unsigned i; bool pass = true; bool log_header = true; bool do_all = false; bool check_errors = true; piglit_require_extension("GL_ARB_texture_compression"); glGetIntegerv(GL_NUM_COMPRESSED_TEXTURE_FORMATS, &num_compressed_formats); if (num_compressed_formats == 0) { printf("No compressed formats supported.\n"); } else { compressed_formats = calloc(num_compressed_formats, sizeof(GLenum)); glGetIntegerv(GL_COMPRESSED_TEXTURE_FORMATS, (GLint *) compressed_formats); printf("Driver reported the following compressed formats:\n"); for (i = 0; i < num_compressed_formats; i++) { printf(" 0x%04x: %s\n", compressed_formats[i], piglit_get_gl_enum_name(compressed_formats[i])); } printf("\n"); fflush(stdout); } /* First scan the list of formats looking for zeros. We use that as * magic flag later in the test. */ for (i = 0; i < num_compressed_formats; i++) { if (compressed_formats[i] == 0) { fprintf(stderr, "Invalid value 0x0000 in format list.\n"); piglit_report_result(PIGLIT_FAIL); } } /* The "unknown" flag instructs the test to just check for values that * don't belong to any compression extension supported by this * implementation. */ if (argc > 1 && strcmp("unknown", argv[1]) == 0) { check_errors = false; argv++; argc--; } if (argc == 1) { argv = (char **) all_formats; /* cast away const */ argc = ARRAY_SIZE(all_formats); do_all = true; } for (i = 1; i < argc; i++) { if (strcmp(argv[i], "bptc") == 0) { pass = try_formats(&bptc_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_ARB_texture_compression_bptc"), true) && pass; } else if (strcmp(argv[i], "s3tc") == 0) { pass = try_formats(&s3tc_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_EXT_texture_compression_s3tc"), false) && pass; } else if (strcmp(argv[i], "fxt1") == 0) { pass = try_formats(&fxt1_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_3DFX_texture_compression_FXT1"), false) && pass; } else if (strcmp(argv[i], "latc") == 0) { pass = try_formats(&latc_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_EXT_texture_compression_latc"), false) && pass; } else if (strcmp(argv[i], "3dc") == 0) { pass = try_formats(&ati_3dc_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_ATI_texture_compression_3dc"), false) && pass; } else if (strcmp(argv[i], "rgtc") == 0) { pass = try_formats(&rgtc_formats, compressed_formats, num_compressed_formats, check_errors, (piglit_is_extension_supported("GL_ARB_texture_compression_rgtc") || piglit_is_extension_supported("GL_EXT_texture_compression_rgtc")), false) && pass; } else if (strcmp(argv[i], "srgb") == 0) { pass = try_formats(&srgb_formats, compressed_formats, num_compressed_formats, check_errors, (piglit_is_extension_supported("GL_EXT_texture_sRGB") && piglit_is_extension_supported("GL_EXT_texture_compression_s3tc")), false) && pass; } else if (strcmp(argv[i], "paletted") == 0) { pass = try_formats(&paletted_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_OES_compressed_paletted_texture"), false) && pass; } else if (strcmp(argv[i], "etc1") == 0) { pass = try_formats(&etc1_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_OES_compressed_ETC1_RGB8_texture"), false) && pass; } else if (strcmp(argv[i], "etc2") == 0) { pass = try_formats(&etc2_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_ARB_ES3_compatibility"), true) && pass; } else if (strcmp(argv[i], "astc") == 0) { pass = try_formats(&astc_formats, compressed_formats, num_compressed_formats, check_errors, piglit_is_extension_supported("GL_KHR_texture_compression_astc_ldr"), false) && pass; } else { fprintf(stderr, "Unrecognized selection `%s'\n", argv[i]); piglit_report_result(PIGLIT_FAIL); } } /* After all of the known formats have been processed, the entire * format array should be zeroed out. Any non-zero values are either * errors or formats from unknown extensions... meaning that the test * may need to be updated. */ if (do_all) { for (i = 0; i < num_compressed_formats; i++) { if (compressed_formats[i] != 0) { if (log_header) { fprintf(stderr, "Unrecognized compressed " "texture formats:\n"); log_header = false; } fprintf(stderr, " 0x%04x: %s\n", compressed_formats[i], piglit_get_gl_enum_name(compressed_formats[i])); pass = false; } } } pass = test_hint() && pass; piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL); }