Note: 3 texture environment functions (modulate, decal and blend) were introduces with OpenGL 1.0. GL 1.1 and 1.3 added the replace and add functions, respectively. As this test tests all 5 functions it is classified as OpenGL 1.3. --- tests/all.py | 1 + tests/spec/gl-1.3/CMakeLists.gl.txt | 1 + tests/spec/gl-1.3/texture-env.c | 526 ++++++++++++++++++++++++++++++++++++ 3 files changed, 528 insertions(+) create mode 100644 tests/spec/gl-1.3/texture-env.c
diff --git a/tests/all.py b/tests/all.py index 3fd1153..3142ad2 100644 --- a/tests/all.py +++ b/tests/all.py @@ -1037,6 +1037,7 @@ with profile.test_list.group_manager( grouptools.join('spec', '!opengl 1.3')) as g: g(['texunits']) g(['tex-border-1']) + g(['gl-1.3-texture-env']) g(['tex3d-depth1']) with profile.test_list.group_manager( diff --git a/tests/spec/gl-1.3/CMakeLists.gl.txt b/tests/spec/gl-1.3/CMakeLists.gl.txt index 607d2c1..8eaa94d 100644 --- a/tests/spec/gl-1.3/CMakeLists.gl.txt +++ b/tests/spec/gl-1.3/CMakeLists.gl.txt @@ -9,5 +9,6 @@ link_libraries ( ) piglit_add_executable (gl-1.3-alpha_to_coverage_nop alpha_to_coverage_nop.c) +piglit_add_executable (gl-1.3-texture-env texture-env.c) # vim: ft=cmake: diff --git a/tests/spec/gl-1.3/texture-env.c b/tests/spec/gl-1.3/texture-env.c new file mode 100644 index 0000000..7b43507 --- /dev/null +++ b/tests/spec/gl-1.3/texture-env.c @@ -0,0 +1,526 @@ +/* + * Copyright (C) 1999 Allen Akin All Rights Reserved. + * + * 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 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 ALLEN AKIN 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 tex-env.c: Test the basic texture env modes + * Author: Brian Paul (bri...@valinux.com) April 2001 + * + * Test procedure: + * Setup a texture with 81 columns of unique RGBA colors, 3 texels each. + * Draw a 81 uniquely-colored flat-shaded quads as wide horizontal bands, + * with the above texture. This makes a matrix of 81*81 colored squares + * for which we test that the current texture environment mode and texture + * format produced the correct color. + * Finally, we blend over a gray background in order to verify that the + * post-texture alpha value is correct. + */ + +#include "piglit-util-gl.h" + +PIGLIT_GL_TEST_CONFIG_BEGIN + + config.supports_gl_compat_version = 13; + config.window_visual = PIGLIT_GL_VISUAL_RGBA; + config.khr_no_error_support = PIGLIT_NO_ERRORS; + config.window_width = 256; + config.window_height = 256; + +PIGLIT_GL_TEST_CONFIG_END + +#define BLEND_WITH_BACKGROUND 1 + +#define COLORS (3 * 3 * 3 * 3) + +static float colors[COLORS][4]; + +static float bg_color[4] = {0.5, 0.5, 0.5, 0.5}; + +static const GLenum format_enums[] = { + GL_ALPHA, + GL_LUMINANCE, + GL_LUMINANCE_ALPHA, + GL_INTENSITY, + GL_RGB, + GL_RGBA +}; + +static const GLenum env_mode_enums[] = { + GL_REPLACE, + GL_MODULATE, + GL_DECAL, + GL_BLEND, + GL_ADD +}; + +/* Compute expected texenv result given the texture env mode, the texture + * base format, texture color, fragment color, and texture env color. + * This also blends the result with the background color if that option + * is enabled (see above). */ +static void +compute_expected_color(GLenum env_mode, GLenum tex_format, + const float tex_color[4], const float frag_color[4], + const float env_color[4], float result[4]) +{ + switch (env_mode) { + case GL_REPLACE: + switch (tex_format) { + case GL_ALPHA: + result[0] = frag_color[0]; + result[1] = frag_color[1]; + result[2] = frag_color[2]; + result[3] = tex_color[3]; /* alpha */ + break; + case GL_LUMINANCE: + result[0] = tex_color[0]; /* lum */ + result[1] = tex_color[0]; + result[2] = tex_color[0]; + result[3] = frag_color[3]; + break; + case GL_LUMINANCE_ALPHA: + result[0] = tex_color[0]; /* lum */ + result[1] = tex_color[0]; + result[2] = tex_color[0]; + result[3] = tex_color[3]; /* alpha */ + break; + case GL_INTENSITY: + result[0] = tex_color[0]; /* intensity */ + result[1] = tex_color[0]; + result[2] = tex_color[0]; + result[3] = tex_color[0]; + break; + case GL_RGB: + result[0] = tex_color[0]; /* r */ + result[1] = tex_color[1]; /* g */ + result[2] = tex_color[2]; /* b */ + result[3] = frag_color[3]; + break; + case GL_RGBA: + result[0] = tex_color[0]; /* r */ + result[1] = tex_color[1]; /* g */ + result[2] = tex_color[2]; /* b */ + result[3] = tex_color[3]; /* a */ + break; + default: + abort(); /* implementation error */ + } + break; + case GL_MODULATE: + switch (tex_format) { + case GL_ALPHA: + result[0] = frag_color[0]; + result[1] = frag_color[1]; + result[2] = frag_color[2]; + result[3] = frag_color[3] * tex_color[3]; + break; + case GL_LUMINANCE: + result[0] = frag_color[0] * tex_color[0]; + result[1] = frag_color[1] * tex_color[0]; + result[2] = frag_color[2] * tex_color[0]; + result[3] = frag_color[3]; + break; + case GL_LUMINANCE_ALPHA: + result[0] = frag_color[0] * tex_color[0]; + result[1] = frag_color[1] * tex_color[0]; + result[2] = frag_color[2] * tex_color[0]; + result[3] = frag_color[3] * tex_color[3]; + break; + case GL_INTENSITY: + result[0] = frag_color[0] * tex_color[0]; + result[1] = frag_color[1] * tex_color[0]; + result[2] = frag_color[2] * tex_color[0]; + result[3] = frag_color[3] * tex_color[0]; + break; + case GL_RGB: + result[0] = frag_color[0] * tex_color[0]; + result[1] = frag_color[1] * tex_color[1]; + result[2] = frag_color[2] * tex_color[2]; + result[3] = frag_color[3]; + break; + case GL_RGBA: + result[0] = frag_color[0] * tex_color[0]; + result[1] = frag_color[1] * tex_color[1]; + result[2] = frag_color[2] * tex_color[2]; + result[3] = frag_color[3] * tex_color[3]; + break; + default: + abort(); /* implementation error */ + } + break; + case GL_DECAL: + switch (tex_format) { + case GL_ALPHA: + result[0] = 0; /* undefined */ + result[1] = 0; + result[2] = 0; + result[3] = 0; + break; + case GL_LUMINANCE: + result[0] = 0; /* undefined */ + result[1] = 0; + result[2] = 0; + result[3] = 0; + break; + case GL_LUMINANCE_ALPHA: + result[0] = 0; /* undefined */ + result[1] = 0; + result[2] = 0; + result[3] = 0; + break; + case GL_INTENSITY: + result[0] = 0; /* undefined */ + result[1] = 0; + result[2] = 0; + result[3] = 0; + break; + case GL_RGB: + result[0] = tex_color[0]; + result[1] = tex_color[1]; + result[2] = tex_color[2]; + result[3] = frag_color[3]; + break; + case GL_RGBA: { + const float a = tex_color[3]; + const float oma = 1.0 - a; + result[0] = frag_color[0] * oma + tex_color[0] * a; + result[1] = frag_color[1] * oma + tex_color[1] * a; + result[2] = frag_color[2] * oma + tex_color[2] * a; + result[3] = frag_color[3]; + } break; + default: + abort(); /* implementation error */ + } + break; + case GL_BLEND: + switch (tex_format) { + case GL_ALPHA: + result[0] = frag_color[0]; + result[1] = frag_color[1]; + result[2] = frag_color[2]; + result[3] = frag_color[3] * tex_color[3]; + break; + case GL_LUMINANCE: { + const float l = tex_color[0]; + const float oml = 1.0 - l; + result[0] = frag_color[0] * oml + env_color[0] * l; + result[1] = frag_color[1] * oml + env_color[1] * l; + result[2] = frag_color[2] * oml + env_color[2] * l; + result[3] = frag_color[3]; + } break; + case GL_LUMINANCE_ALPHA: { + const float l = tex_color[0]; + const float oml = 1.0 - l; + result[0] = frag_color[0] * oml + env_color[0] * l; + result[1] = frag_color[1] * oml + env_color[1] * l; + result[2] = frag_color[2] * oml + env_color[2] * l; + result[3] = frag_color[3] * tex_color[3]; + } break; + case GL_INTENSITY: { + const float i = tex_color[0]; + const float omi = 1.0 - i; + result[0] = frag_color[0] * omi + env_color[0] * i; + result[1] = frag_color[1] * omi + env_color[1] * i; + result[2] = frag_color[2] * omi + env_color[2] * i; + result[3] = frag_color[3] * omi + env_color[3] * i; + } break; + case GL_RGB: { + const float r = tex_color[0]; + const float omr = 1.0 - r; + const float g = tex_color[1]; + const float omg = 1.0 - g; + const float b = tex_color[2]; + const float omb = 1.0 - b; + result[0] = frag_color[0] * omr + env_color[0] * r; + result[1] = frag_color[1] * omg + env_color[1] * g; + result[2] = frag_color[2] * omb + env_color[2] * b; + result[3] = frag_color[3]; + } break; + case GL_RGBA: { + const float r = tex_color[0]; + const float omr = 1.0 - r; + const float g = tex_color[1]; + const float omg = 1.0 - g; + const float b = tex_color[2]; + const float omb = 1.0 - b; + result[0] = frag_color[0] * omr + env_color[0] * r; + result[1] = frag_color[1] * omg + env_color[1] * g; + result[2] = frag_color[2] * omb + env_color[2] * b; + result[3] = frag_color[3] * tex_color[3]; + } break; + default: + abort(); /* implementation error */ + } + break; + case GL_ADD: + switch (tex_format) { + case GL_ALPHA: + result[0] = frag_color[0]; + result[1] = frag_color[1]; + result[2] = frag_color[2]; + result[3] = frag_color[3] * tex_color[3]; + break; + case GL_LUMINANCE: + result[0] = frag_color[0] + tex_color[0]; + result[1] = frag_color[1] + tex_color[0]; + result[2] = frag_color[2] + tex_color[0]; + result[3] = frag_color[3]; + break; + case GL_LUMINANCE_ALPHA: + result[0] = frag_color[0] + tex_color[0]; + result[1] = frag_color[1] + tex_color[0]; + result[2] = frag_color[2] + tex_color[0]; + result[3] = frag_color[3] * tex_color[3]; + break; + case GL_INTENSITY: + result[0] = frag_color[0] + tex_color[0]; + result[1] = frag_color[1] + tex_color[0]; + result[2] = frag_color[2] + tex_color[0]; + result[3] = frag_color[3] + tex_color[0]; + break; + case GL_RGB: + result[0] = frag_color[0] + tex_color[0]; + result[1] = frag_color[1] + tex_color[1]; + result[2] = frag_color[2] + tex_color[2]; + result[3] = frag_color[3]; + break; + case GL_RGBA: + result[0] = frag_color[0] + tex_color[0]; + result[1] = frag_color[1] + tex_color[1]; + result[2] = frag_color[2] + tex_color[2]; + result[3] = frag_color[3] * tex_color[3]; + break; + default: + abort(); /* implementation error */ + } + /* clamping */ + if (result[0] > 1.0) + result[0] = 1.0; + if (result[1] > 1.0) + result[1] = 1.0; + if (result[2] > 1.0) + result[2] = 1.0; + if (result[3] > 1.0) + result[3] = 1.0; + break; + default: + abort(); /* implementation error */ + } + +#if BLEND_WITH_BACKGROUND + /* now blend result over a gray background */ + const float alpha = result[3]; + const float om_alpha = 1.0 - alpha; + result[0] = result[0] * alpha + bg_color[0] * om_alpha; + result[1] = result[1] * alpha + bg_color[1] * om_alpha; + result[2] = result[2] * alpha + bg_color[2] * om_alpha; + result[3] = result[3] * alpha + bg_color[3] * om_alpha; +#endif +} + +/* Make a texture in which the colors vary along the length + * according to the colors[] array. For example, we use + * 243 columns of the texture to store 81 colors, 3 texels each. */ +static void +make_tex_image(GLenum base_format, int num_colors, const float colors[][4]) +{ +#define WIDTH 256 +#define HEIGHT 4 + static float img[WIDTH * HEIGHT][4]; + + assert(num_colors == 81); + + for (int i = 0; i < HEIGHT; i++) { + for (int j = 0; j < WIDTH; j++) { + int c = j / 3; + if (c >= num_colors) { + img[i * WIDTH + j][0] = 0.0; + img[i * WIDTH + j][1] = 0.0; + img[i * WIDTH + j][2] = 0.0; + img[i * WIDTH + j][3] = 0.0; + } else { + img[i * WIDTH + j][0] = colors[c][0]; + img[i * WIDTH + j][1] = colors[c][1]; + img[i * WIDTH + j][2] = colors[c][2]; + img[i * WIDTH + j][3] = colors[c][3]; + } + } + } + + glTexImage2D(GL_TEXTURE_2D, 0, base_format, WIDTH, HEIGHT, 0, GL_RGBA, + GL_FLOAT, (void *)img); +} + +/* Do num_colors * num_colors tests in one batch. + * Setup a texture in which the colors vary by column. + * Draw a quadstrip in which we draw horizontal bands of colors. + * Drawing the textured quadstrips will fill the window with + * num_colors * num_colors test squares. + * Verify that they're all correct. + * Return: true = pass, false = fail */ +static bool +matrix_test(GLenum env_mode, GLenum tex_format, int num_colors, + const float colors[][4], const float env_color[4]) +{ + const char *format_name = piglit_get_gl_enum_name(tex_format); + const char *env_name = piglit_get_gl_enum_name(env_mode); + + if (env_mode == GL_DECAL && + (tex_format != GL_RGB && tex_format != GL_RGBA)) { + /* undefined mode */ + return true; + } + + glClear(GL_COLOR_BUFFER_BIT); + + /* The texture colors are the columns */ + make_tex_image(tex_format, num_colors, colors); + + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, env_mode); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, env_color); + + /* The fragment colors are the rows */ + float W = num_colors * 3; + float S = (float)(num_colors * 3) / (float)256; + glBegin(GL_QUAD_STRIP); + glTexCoord2f(0, 0); glVertex2f(0, 0); + glTexCoord2f(S, 0); glVertex2f(W, 0); + for (int i = 0; i < num_colors; i++) { + glColor4fv(colors[i]); + float y = i * 3 + 3; + float t = y / (num_colors * 3); + glTexCoord2f(0, t); glVertex2f(0, y); + glTexCoord2f(S, t); glVertex2f(W, y); + } + glEnd(); + + /* Check results */ + for (int row = 0; row < num_colors; row++) { + for (int col = 0; col < num_colors; col++) { + + /* compute expected */ + float expected[4]; + compute_expected_color(env_mode, tex_format, + colors[col], colors[row], + env_color, expected); + + /* fetch actual pixel */ + int x = col * 3 + 1; + int y = row * 3 + 1; + + /* compare */ + if (!piglit_probe_pixel_rgba(x, y, expected)) { + /* Report the error */ + printf("GL_TEXTURE_ENV_MODE = %s\n" + "Texture Format = %s\n" + "Fragment Color = (%f, %f, %f, %f)\n" + "Texture Color = (%f, %f, %f, %f)\n" + "Tex Env Color = (%f, %f, %f, %f)\n", + env_name, format_name, + colors[row][0], colors[row][1], + colors[row][2], colors[row][3], + colors[col][0], colors[col][1], + colors[col][2], colors[col][3], + env_color[0], env_color[1], + env_color[2], env_color[3]); +#if BLEND_WITH_BACKGROUND + printf("Blend over = (%f, %f, %f, %f)\n", + bg_color[0], bg_color[1], + bg_color[2], bg_color[3]); +#endif + return false; + } + } + } + return true; +} + +enum piglit_result +piglit_display(void) +{ + bool pass = true; + + for (int fmt = 0; fmt < 6; fmt++) { + const GLenum format = format_enums[fmt]; + for (int mode = 0; mode < 5; mode++) { + const GLenum env_mode = env_mode_enums[mode]; + if (env_mode == GL_BLEND && format != GL_ALPHA) { + /* also vary texenv color, every 5th is OK. */ + for (int i = 0; i < COLORS; i += 5) { + const float *env_color = colors[i]; + if (!matrix_test(env_mode, format, + COLORS, colors, + env_color)) { + pass = false; + break; + } + } + } else { + /* texenv color not significant */ + if (!matrix_test(env_mode, format, COLORS, + colors, colors[0])) { + pass = false; + } + } + } + } + + return pass ? PIGLIT_PASS : PIGLIT_FAIL; +} + +void +piglit_init(int argc, char **argv) +{ + GLuint texture; + + /* colors[] is an array of all possible RGBA colors with component + * values of 0, 0.5, and 1.0 */ + for (int i = 0; i < COLORS; i++) { + int r = i % 3; + int g = (i / 3) % 3; + int b = (i / 9) % 3; + int a = (i / 27) % 3; + colors[i][0] = (float)r / 2.0; + colors[i][1] = (float)g / 2.0; + colors[i][2] = (float)b / 2.0; + colors[i][3] = (float)a / 2.0; + } + + 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); + glEnable(GL_TEXTURE_2D); + +#if BLEND_WITH_BACKGROUND + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + glEnable(GL_BLEND); +#endif + + glClearColor(bg_color[0], bg_color[1], bg_color[2], bg_color[3]); + glShadeModel(GL_FLAT); + + piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE); +} -- 2.7.4 _______________________________________________ Piglit mailing list Piglit@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/piglit