/* * Copyright (c) The Piglit project 2008 * * 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 * on the rights to use, copy, modify, merge, publish, distribute, sub * license, 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 NON-INFRINGEMENT. IN NO EVENT SHALL * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS 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 * Tests 3D textures. */ #include "piglit-util-gl.h" PIGLIT_GL_TEST_CONFIG_BEGIN config.supports_gl_compat_version = 10; config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE; config.khr_no_error_support = PIGLIT_NO_ERRORS; PIGLIT_GL_TEST_CONFIG_END static GLuint Texture; static int nrcomponents(GLenum format) { switch(format) { case GL_RGBA: return 4; case GL_RGB: return 3; case GL_ALPHA: return 1; default: abort(); } } static void expected_rgba(GLenum format, const GLubyte *texdata, GLubyte *expected) { switch(format) { case GL_RGBA: expected[0] = texdata[0]; expected[1] = texdata[1]; expected[2] = texdata[2]; expected[3] = texdata[3]; return; case GL_RGB: expected[0] = texdata[0]; expected[1] = texdata[1]; expected[2] = texdata[2]; expected[3] = 255; return; case GL_ALPHA: expected[0] = 255; expected[1] = 255; expected[2] = 255; expected[3] = texdata[0]; return; } } static bool render_and_check(int w, int h, int d, GLenum format, float q, const GLubyte *data, const char* test) { int x, y, z; int layer; GLubyte *readback; const GLubyte *texp; GLubyte *readp; int ncomp = 0; glClearColor(0.0, 0.0, 0.0, 0.0); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_3D); x = y = 0; for(layer = 0; layer < d; ++layer) { float r = (layer+0.5)/d; glBegin(GL_QUADS); glTexCoord4f(0, 0, r*q, q); glVertex2f(x, y); glTexCoord4f(q, 0, r*q, q); glVertex2f(x+w, y); glTexCoord4f(q, q, r*q, q); glVertex2f(x+w, y+h); glTexCoord4f(0, q, r*q, q); glVertex2f(x, y+h); glEnd(); x += w; if (x+w >= piglit_width) { y += h; x = 0; } } readback = (unsigned char*)malloc(w*h*d*4); x = y = 0; for(layer = 0; layer < d; ++layer) { glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, readback+layer*w*h*4); x += w; if (x+w >= piglit_width) { y += h; x = 0; } } texp = data; readp = readback; ncomp = nrcomponents(format); for(z = 0; z < d; ++z) { for(y = 0; y < h; ++y) { for(x = 0; x < w; ++x, readp += 4, texp += ncomp) { unsigned char expected[4]; int i; expected_rgba(format, texp, expected); for(i = 0; i < 4; ++i) { if (expected[i] != readp[i]) { fprintf(stderr, "%s: Mismatch at %ix%ix%i\n", test, x, y, z); fprintf(stderr, " Expected: %i,%i,%i,%i\n", expected[0], expected[1], expected[2], expected[3]); fprintf(stderr, " Readback: %i,%i,%i,%i\n", readp[0], readp[1], readp[2], readp[3]); free(readback); return false; } } } } } free(readback); piglit_present_results(); return true; } /** * Load non-mipmapped 3D texture of the given size * and check whether it is rendered correctly. */ static bool test_simple(int w, int h, int d, GLenum format) { int size; unsigned char *data; int i; bool success = true; assert(1 <= w && w <= 16); assert(1 <= h && h <= 16); assert(1 <= d && d <= 16); assert(format == GL_RGBA || format == GL_RGB || format == GL_ALPHA); size = w*h*d*nrcomponents(format); data = (unsigned char*)malloc(size); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); srand(size); /* Generate reproducible image data */ for(i = 0; i < size; ++i) data[i] = rand() & 255; glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexImage3D(GL_TEXTURE_3D, 0, format, w, h, d, 0, format, GL_UNSIGNED_BYTE, data); success = success && render_and_check(w, h, d, format, 1.0, data, "Render 3D texture"); success = success && render_and_check(w, h, d, format, 1.4, data, "Render 3D texture (q != 1.0)"); free(data); if (!success) { fprintf(stderr, "Failure with texture size %ix%ix%i, format = %s\n", w, h, d, piglit_get_gl_enum_name(format)); } return success; } enum piglit_result piglit_display(void) { GLenum formats[] = { GL_RGBA, GL_RGB, GL_ALPHA }; int w, h, d, fmt; bool pass = true; piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); for(fmt = 0; fmt < sizeof(formats)/sizeof(formats[0]); ++fmt) { for(w = 3; w <= 15; w++) { if (w != 4 && w != 8) { for(h = 3; h <= 15; h++) { if (h != 4 && h != 8) { for(d = 3; d <= 15; d++) { if (d != 4 && d != 8) { pass = test_simple(w, h, d, formats[fmt]); if (!pass) goto end; } } } } } } } end: return pass ? PIGLIT_PASS : PIGLIT_FAIL; } void piglit_init(int argc, char **argv) { piglit_require_extension("GL_ARB_texture_non_power_of_two"); glDisable(GL_DITHER); glGenTextures(1, &Texture); glBindTexture(GL_TEXTURE_3D, Texture); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); }