/* * 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 * Test whether resizing a texture and switching from/to mipmapping * works correctly. */ #include #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 const int CellSize = 8; /* see cell_coords */ static int testnr; static void make_color(int nr, float* result) { int i; for(i = 0; i < 4; ++i) { result[i] = ((nr & 3) + 1) * 0.2; nr >>= 2; } } static void cell_coords(int cellnr, int *px, int *py) { *px = CellSize * (cellnr & 15); /* Hard-coded things! */ *py = CellSize * (cellnr / 16); assert(cellnr < 256); } /** Load a texture image with a constant color generated by \ref make_color */ static void teximage2d(GLuint lvl, GLuint w, GLuint h, int colornum) { float color[4]; float* tex; int i; make_color(colornum, color); tex = (float*)malloc(w*h*4*sizeof(float)); for(i = 0; i < w*h; ++i) { tex[4*i] = color[0]; tex[4*i + 1] = color[1]; tex[4*i + 2] = color[2]; tex[4*i + 3] = color[3]; } glTexImage2D(GL_TEXTURE_2D, lvl, GL_RGBA, w, h, 0, GL_RGBA, GL_FLOAT, tex); free(tex); } /** Render the given texture level into the given cell and verify the resulting color*/ static int cell(int cellnr, int lvl, GLuint basew, GLuint baseh, int colornr, const char* testnamefmt, ...) { float color[4]; float *readback; float tcx = (float)CellSize / basew * (1 << lvl); float tcy = (float)CellSize / baseh * (1 << lvl); int cellx, celly; int x, y; make_color(colornr, color); cell_coords(cellnr, &cellx, &celly); glBegin(GL_QUADS); glTexCoord2f(0, 0); glVertex2f(cellx, celly); glTexCoord2f(tcx, 0); glVertex2f(cellx+CellSize, celly); glTexCoord2f(tcx, tcy); glVertex2f(cellx+CellSize, celly+CellSize); glTexCoord2f(0, tcy); glVertex2f(cellx, celly+CellSize); glEnd(); readback = (float*)malloc(CellSize*CellSize*4*sizeof(float)); glReadPixels(cellx, celly, CellSize, CellSize, GL_RGBA, GL_FLOAT, readback); for(y = 0; y < CellSize; ++y) { for(x = 0; x < CellSize; ++x) { float *read = readback + 4*(y*CellSize + x); float eps = 0.01; if (fabs(read[0] - color[0]) > eps || fabs(read[1] - color[1]) > eps || fabs(read[2] - color[2]) > eps || fabs(read[3] - color[3]) > eps) { va_list args; va_start(args, testnamefmt); fprintf(stderr, "Test #%i failed: ", cellnr+1); vfprintf(stderr, testnamefmt, args); fprintf(stderr, "\n First failing pixel %i,%i in cell at %d,%d\n", x, y, cellx, celly); fprintf(stderr, " Expected: %f %f %f %f\n", color[0], color[1], color[2], color[3]); fprintf(stderr, " Readback: %f %f %f %f\n", read[0], read[1], read[2], read[3]); va_end(args); free(readback); return 0; } } } free(readback); return 1; } /** Run a couple of tests with the given base texture size */ static int test_size(GLuint basew, GLuint baseh) { int lvls, lvl; GLuint w = basew; GLuint h = baseh; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); teximage2d(0, w, h, testnr); if (!cell(testnr, 0, basew, baseh, testnr, "Nearest filtering, base size %ix%i", basew, baseh)) return 0; testnr++; glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST); for(lvls = 0; w >= 1 || h >= 1; lvls++, w >>= 1, h >>= 1) { if (!w) w = 1; if (!h) h = 1; teximage2d(lvls, w, h, testnr+lvls); } for(lvl = 0; lvl < lvls; ++lvl) { if (!cell(testnr+lvl, lvl, basew, baseh, testnr+lvl, "Mip filtering, base size %ix%i, level %i", basew, baseh, lvl)) return 0; } testnr += lvls; return 1; } struct size { GLuint w, h; }; static const struct size sizes[] = { { 16, 16 }, { 32, 16 }, { 16, 32 }, { 32, 32 }, { 16, 16 } }; enum piglit_result piglit_display(void) { GLboolean pass = GL_TRUE; int sizeidx; testnr = 0; piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); glClearColor(0.5, 0.5, 0.5, 1.0); glClear(GL_COLOR_BUFFER_BIT); glEnable(GL_TEXTURE_2D); for(sizeidx = 0; sizeidx < sizeof(sizes)/sizeof(sizes[0]); ++sizeidx) { if (!test_size(sizes[sizeidx].w, sizes[sizeidx].h)) { pass = GL_FALSE; } } glDisable(GL_TEXTURE_2D); piglit_present_results(); return pass ? PIGLIT_PASS : PIGLIT_FAIL; } void piglit_init(int argc, char **argv) { }