/* * Copyright (c) 2011 VMware, Inc. * * 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 VMWARE 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. */ /** * Tests GL_ARB_texture_float floating point formats */ #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; PIGLIT_GL_TEST_CONFIG_END static const char *TestName = "texture-float-formats"; static GLint TexWidth = 16, TexHeight = 16; static GLint BiasUniform = -1, ScaleUniform = -1, TexUniform = -1; static const float Scale = 1.0 / 2000.0, Bias = 0.5; static GLboolean HaveRG; struct format_info { GLenum IntFormat, BaseFormat; GLuint BitsPerChannel; }; static const struct format_info Formats[] = { { GL_RGBA32F_ARB, GL_RGBA, 32 }, { GL_RGB32F_ARB, GL_RGB, 32 }, { GL_ALPHA32F_ARB, GL_ALPHA, 32 }, { GL_INTENSITY32F_ARB, GL_INTENSITY, 32 }, { GL_LUMINANCE32F_ARB, GL_LUMINANCE, 32 }, { GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE, 32 }, { GL_RGBA16F_ARB, GL_RGBA, 16 }, { GL_RGB16F_ARB, GL_RGB, 16 }, { GL_ALPHA16F_ARB, GL_ALPHA, 16 }, { GL_INTENSITY16F_ARB, GL_INTENSITY, 16 }, { GL_LUMINANCE16F_ARB, GL_LUMINANCE, 16 }, { GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE, 16 }, /* These require GL_ARB_texture_rg */ { GL_R32F, GL_RED, 32 }, { GL_RG32F, GL_RG, 32 }, { GL_R16F, GL_RED, 16 }, { GL_RG16F, GL_RG, 16 }, }; static const char *FragShaderText = "uniform float bias, scale; \n" "uniform sampler2D tex; \n" "void main() \n" "{ \n" " vec4 t = vec4(texture2D(tex, gl_TexCoord[0].xy)); \n" " gl_FragColor = t * scale + bias; \n" "} \n"; static GLuint Program; static int num_components(GLenum format) { switch (format) { case GL_RGBA: return 4; case GL_RGB: return 3; case GL_ALPHA: return 1; case GL_INTENSITY: return 1; case GL_LUMINANCE: return 1; case GL_LUMINANCE_ALPHA: return 2; case GL_RED: return 1; case GL_RG: return 2; default: assert(0); return 0; } } static void fill_array(int comps, int texels, void *buf, const float val[4]) { GLfloat *f = (GLfloat *) buf; int i, j; for (i = 0; i < texels; i++) { for (j = 0; j < comps; j++) { f[i * comps + j] = val[j]; } } } static GLboolean check_error(const char *file, int line) { GLenum err = glGetError(); if (err) { printf("%s: error 0x%x at %s:%d\n", TestName, err, file, line); return GL_TRUE; } return GL_FALSE; } /** Scale a float in [-1000, 1000] to [0, 1] */ static float scale_and_bias(float val) { return val * Scale + Bias; } /** * Get a color to use for filling the texture image. * Range of values is [-1000, 1000] */ static void get_texture_color(GLfloat value[4]) { static const GLfloat colors[12][4] = { { 690.0, 633.0, -649.0, -975.0 }, { 409.0, -678.0, 624.0, -976.0 }, { -460.0, -102.0, -983.0, 120.0 }, { 202.0, 75.0, 826.0, -339.0 }, { -709.0, 620.0, 204.0, -666.0 }, { 718.0, -299.0, 290.0, 383.0 }, { 634.0, 235.0, 571.0, -651.0 }, { -984.0, -99.0, 448.0, 263.0 }, { -466.0, 356.0, -155.0, 500.0 }, { 678.0, -531.0, 81.0, -783.0 }, { -76.0, 98.0, -106.0, -875.0 }, { 730.0, -723.0, -656.0, -980.0 } }; static int i = 0; value[0] = colors[i][0]; value[1] = colors[i][1]; value[2] = colors[i][2]; value[3] = colors[i][3]; i = (i + 1) % 12; } /** \return GL_TRUE for pass, GL_FALSE for fail */ static GLboolean test_format(const struct format_info *info) { const int comps = num_components(info->BaseFormat); const int texels = TexWidth * TexHeight; const int w = piglit_width / 10; const int h = piglit_height / 10; GLfloat expected[4]; void *image; float value[4]; GLint f; GLenum userFormat; int p; const char *name = piglit_get_gl_enum_name(info->IntFormat); if ((info->BaseFormat == GL_RED || info->BaseFormat == GL_RG) && !HaveRG) { /* skip it */ return GL_TRUE; } /*printf("Testing %s\n", name);*/ get_texture_color(value); /* alloc, fill texture image */ image = malloc(comps * texels * sizeof(GLfloat)); fill_array(comps, texels, image, value); /* GL_INTENSITY is not a legal src format */ userFormat = info->BaseFormat == GL_INTENSITY ? GL_LUMINANCE : info->BaseFormat; glTexImage2D(GL_TEXTURE_2D, 0, info->IntFormat, TexWidth, TexHeight, 0, userFormat, GL_FLOAT, image); free(image); if (check_error(__FILE__, __LINE__)) return GL_FALSE; /* check internal format */ glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &f); if (f != info->IntFormat) { printf("%s: GL_TEXTURE_INTERNAL_FORMAT query failed for 0x%x\n", TestName, info->IntFormat); return GL_FALSE; } /* check texture datatype info */ { static const GLenum queries[] = { GL_TEXTURE_RED_TYPE_ARB, GL_TEXTURE_GREEN_TYPE_ARB, GL_TEXTURE_BLUE_TYPE_ARB, GL_TEXTURE_ALPHA_TYPE_ARB, GL_TEXTURE_LUMINANCE_TYPE_ARB, GL_TEXTURE_INTENSITY_TYPE_ARB, GL_TEXTURE_DEPTH_TYPE_ARB }; int i; for (i = 0; i < ARRAY_SIZE(queries); i++) { GLint type = 1; glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, queries[i], &type); if (check_error(__FILE__, __LINE__)) return GL_FALSE; if (type != GL_NONE && type != GL_FLOAT) { printf("%s: %s query failed (returned 0x%x)\n", TestName, piglit_get_gl_enum_name(queries[i]), type); return GL_FALSE; } } } /* compute expected color */ switch (info->BaseFormat) { case GL_RGBA: expected[0] = scale_and_bias(value[0]); expected[1] = scale_and_bias(value[1]); expected[2] = scale_and_bias(value[2]); expected[3] = scale_and_bias(value[3]); break; case GL_RGB: expected[0] = scale_and_bias(value[0]); expected[1] = scale_and_bias(value[1]); expected[2] = scale_and_bias(value[2]); expected[3] = scale_and_bias(1.0); break; case GL_ALPHA: expected[0] = expected[1] = expected[2] = scale_and_bias(0.0); expected[3] = scale_and_bias(value[0]); break; case GL_LUMINANCE: expected[0] = expected[1] = expected[2] = scale_and_bias(value[0]); expected[3] = scale_and_bias(1.0); break; case GL_INTENSITY: expected[0] = expected[1] = expected[2] = expected[3] = scale_and_bias(value[0]); break; case GL_LUMINANCE_ALPHA: expected[0] = expected[1] = expected[2] = scale_and_bias(value[0]); expected[3] = scale_and_bias(value[1]); break; case GL_RED: expected[0] = scale_and_bias(value[0]); expected[1] = scale_and_bias(0.0); expected[2] = scale_and_bias(0.0); expected[3] = scale_and_bias(1.0); break; case GL_RG: expected[0] = scale_and_bias(value[0]); expected[1] = scale_and_bias(value[1]); expected[2] = scale_and_bias(0.0); expected[3] = scale_and_bias(1.0); break; default: abort(); } /* draw */ glClearColor(0.5, 0.5, 0.5, 0.0); glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON); glTexCoord2f(0, 0); glVertex2f(0, 0); glTexCoord2f(1, 0); glVertex2f(w, 0); glTexCoord2f(1, 1); glVertex2f(w, h); glTexCoord2f(0, 1); glVertex2f(0, h); glEnd(); /* test */ p = piglit_probe_pixel_rgba(w/2, h/2, expected); if (!p) { int i; printf(" Failed with format %s:\n", name); printf(" Texture color = "); for (i = 0; i < comps; i++) { printf("%f", value[i]); if (i + 1 < comps) printf(", "); } printf("\n"); } piglit_present_results(); return p; } enum piglit_result piglit_display(void) { int f; GLboolean pass = GL_TRUE; for (f = 0; f < ARRAY_SIZE(Formats); f++) if (!test_format(&Formats[f])) pass = GL_FALSE; return pass ? PIGLIT_PASS : PIGLIT_FAIL; } void piglit_init(int argc, char **argv) { GLuint Texture; piglit_require_extension("GL_ARB_texture_float"); piglit_require_extension("GL_ARB_fragment_shader"); HaveRG = piglit_is_extension_supported("GL_ARB_texture_rg"); Program = piglit_build_simple_program(NULL, FragShaderText); glUseProgram(Program); BiasUniform = glGetUniformLocation(Program, "bias"); ScaleUniform = glGetUniformLocation(Program, "scale"); TexUniform = glGetUniformLocation(Program, "tex"); glUniform1f(BiasUniform, Bias); glUniform1f(ScaleUniform, Scale); glUniform1i(TexUniform, 0); /* tex unit zero */ (void) check_error(__FILE__, __LINE__); glGenTextures(1, &Texture); glBindTexture(GL_TEXTURE_2D, Texture); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); }