/* * 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 compressedteximage.c * * Tests that fetching and uploading compressed texture data works * correctly. * * The other compressed texture tests are about decoding of data that * was uploaded from uncompressed, while this tries a round-trip after * the initial upload, tesitng glGetCompressedTexImage() and * glCompressedTexImage2D(). */ #include "piglit-util-gl-common.h" #define SIZE 128 PIGLIT_GL_TEST_MAIN( (SIZE * 2) + 60 /*window_width*/, SIZE + 20 /*window_height*/, GLUT_RGB | GLUT_DOUBLE) struct format { const char *name; GLenum token; int bw, bh, bs; const char **extension; }; static struct format *format; const char *FXT1[] = { "GL_3DFX_texture_compression_FXT1", NULL }; const char *S3TC[] = { "GL_EXT_texture_compression_s3tc", NULL }; const char *S3TC_srgb[] = { "GL_EXT_texture_compression_s3tc", "GL_EXT_texture_sRGB", NULL }; const char *RGTC[] = { "GL_ARB_texture_compression_rgtc", NULL }; const char *RGTC_signed[] = { "GL_ARB_texture_compression_rgtc", "GL_EXT_texture_snorm", NULL }; #define FORMAT(t, bw, bh, bs, ext) { #t, t, bw, bh, bs, ext } static struct format formats[] = { FORMAT(GL_COMPRESSED_RGB_FXT1_3DFX, 8, 4, 16, FXT1), FORMAT(GL_COMPRESSED_RGBA_FXT1_3DFX, 8, 4, 16, FXT1), FORMAT(GL_COMPRESSED_RGB_S3TC_DXT1_EXT, 4, 4, 8, S3TC), FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, 4, 4, 8, S3TC), FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 16, S3TC), FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, 4, 4, 16, S3TC), FORMAT(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, 4, 4, 8, S3TC_srgb), FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 4, 4, 8, S3TC_srgb), FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 4, 4, 16, S3TC_srgb), FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 4, 4, 16, S3TC_srgb), FORMAT(GL_COMPRESSED_RED_RGTC1_EXT, 4, 4, 8, RGTC), FORMAT(GL_COMPRESSED_SIGNED_RED_RGTC1_EXT, 4, 4, 8, RGTC_signed), FORMAT(GL_COMPRESSED_RED_GREEN_RGTC2_EXT, 4, 4, 16, RGTC), FORMAT(GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT, 4, 4, 16, RGTC_signed), }; static int align(int v, int a) { return (v + a - 1) & ~(a - 1); } static void display_mipmaps(int x, int y) { int i; glEnable(GL_TEXTURE_2D); /* Disply all the mipmap levels */ for (i = SIZE; i > 0; i /= 2) { piglit_draw_rect_tex(x, y, i, i, 0, 0, 1, 1); x += i + 5; } } static GLboolean check_resulting_mipmaps(int x, int y) { GLboolean pass = GL_TRUE; int size; float red[4] = {1.0, 0.0, 0.0, 1.0}; float green[4] = {0.0, 1.0, 0.0, 1.0}; float blue[4] = {0.0, 0.0, 1.0, 1.0}; float white[4] = {1.0, 1.0, 1.0, 1.0}; /* for r, rg textures, overwrite what the expected colors are. */ if (format->token == GL_COMPRESSED_RED_RGTC1_EXT || format->token == GL_COMPRESSED_SIGNED_RED_RGTC1_EXT) { green[1] = 0; blue[2] = 0; white[1] = 0; white[2] = 0; } if (format->token == GL_COMPRESSED_RED_GREEN_RGTC2_EXT || format->token == GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT) { blue[2] = 0; white[2] = 0; } for (size = SIZE; size > 0; size /= 2) { if (size == 4) pass = pass && piglit_probe_pixel_rgb(x + 2, y + 2, red); else if (size == 2) pass = pass && piglit_probe_pixel_rgb(x + 1, y + 1, green); else if (size == 1) pass = pass && piglit_probe_pixel_rgb(x, y, blue); else { pass = pass && piglit_probe_pixel_rgb(x + size / 4, y + size / 4, red); pass = pass && piglit_probe_pixel_rgb(x + size * 3 / 4, y + size / 4, green); pass = pass && piglit_probe_pixel_rgb(x + size / 4, y + size * 3 / 4, blue); pass = pass && piglit_probe_pixel_rgb(x + size * 3 / 4, y + size * 3 / 4, white); } x += size + 5; } return pass; } enum piglit_result piglit_display(void) { GLuint tex, tex_src; bool pass; int level; glClearColor(0.5, 0.5, 0.5, 0.5); glClear(GL_COLOR_BUFFER_BIT); tex_src = piglit_rgbw_texture(format->token, SIZE, SIZE, GL_TRUE, GL_FALSE, GL_UNSIGNED_NORMALIZED); glGenTextures(1, &tex); for (level = 0; (SIZE >> level) > 0; level++) { int w, h, w_a, h_a; int expected_size, size; void *compressed; w = SIZE >> level; h = SIZE >> level; w_a = align(w, format->bw); h_a = align(h, format->bh); expected_size = ((w_a / format->bw) * (h_a / format->bh)) * format->bs; glBindTexture(GL_TEXTURE_2D, tex_src); glGetTexLevelParameteriv(GL_TEXTURE_2D, level, GL_TEXTURE_COMPRESSED_IMAGE_SIZE, &size); if (size != expected_size) { fprintf(stderr, "Format %s level %d (%dx%d) size %d " "doesn't match expected size %d\n", format->name, level, w, h, size, expected_size); piglit_report_result(PIGLIT_FAIL); } compressed = malloc(size); glGetCompressedTexImage(GL_TEXTURE_2D, level, compressed); glBindTexture(GL_TEXTURE_2D, tex); glCompressedTexImage2D(GL_TEXTURE_2D, level, format->token, w, h, 0, size, compressed); if (!piglit_check_gl_error(GL_NO_ERROR)) piglit_report_result(PIGLIT_FAIL); free(compressed); } glDeleteTextures(1, &tex_src); glBindTexture(GL_TEXTURE_2D, tex); display_mipmaps(10, 10); pass = check_resulting_mipmaps(10, 10); piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; } static void usage(int argc, char **argv) { int i; fprintf(stderr, "Usage: %s \n", argv[0]); fprintf(stderr, "format is one of:\n"); for (i = 0; i < ARRAY_SIZE(formats); i++) { fprintf(stderr, " %s\n", formats[i].name); } exit(1); } void piglit_init(int argc, char **argv) { int i; piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); if (argc != 2) usage(argc, argv); format = NULL; for (i = 0; i < ARRAY_SIZE(formats); i++) { if (strcmp(formats[i].name, argv[1]) == 0) { format = &formats[i]; break; } } if (!format) usage(argc, argv); for (i = 0; format->extension[i]; i++) piglit_require_extension(format->extension[i]); }