diff options
author | Fabian Bieler <fabianbieler@fastmail.fm> | 2017-11-14 14:47:00 -0700 |
---|---|---|
committer | Brian Paul <brianp@vmware.com> | 2017-11-15 16:06:46 -0700 |
commit | f2a607305f9922c72d221a46983ddb746fceaee3 (patch) | |
tree | 05b59ad77a02c1d5f3fe7f34dbdd4adf6ba7ddce | |
parent | ae450b1ab76cdfa9278afe9b4988a4aca3a46dc0 (diff) |
Port texture env combine test from Glean to Piglit
Reviewed-by: Brian Paul <brianp@vmware.com>
-rw-r--r-- | tests/all.py | 5 | ||||
-rw-r--r-- | tests/llvmpipe.py | 1 | ||||
-rw-r--r-- | tests/quick.py | 7 | ||||
-rw-r--r-- | tests/spec/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/spec/ext_texture_env_combine/CMakeLists.gl.txt | 11 | ||||
-rw-r--r-- | tests/spec/ext_texture_env_combine/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/spec/ext_texture_env_combine/combine.c | 1276 |
7 files changed, 1302 insertions, 0 deletions
diff --git a/tests/all.py b/tests/all.py index 3f34c4953..a0fcac9e5 100644 --- a/tests/all.py +++ b/tests/all.py @@ -2858,6 +2858,11 @@ with profile.test_list.group_manager( with profile.test_list.group_manager( PiglitGLTest, + grouptools.join('spec', 'ext_texture_env_combine')) as g: + g(['ext_texture_env_combine-combine'], 'texture-env-combine') + +with profile.test_list.group_manager( + PiglitGLTest, grouptools.join('spec', 'arb_texture_env_crossbar')) as g: g(['crossbar'], run_concurrent=False) diff --git a/tests/llvmpipe.py b/tests/llvmpipe.py index 52168c433..93a4664c0 100644 --- a/tests/llvmpipe.py +++ b/tests/llvmpipe.py @@ -28,6 +28,7 @@ remove(join('glean', 'texCombine')) remove(join('spec', '!OpenGL 1.0', 'gl-1.0-blend-func')) remove(join('spec', '!OpenGL 1.1', 'streaming-texture-leak')) remove(join('spec', '!OpenGL 1.1', 'max-texture-size')) +remove(join('spec', 'ext_texture_env_combine', 'ext_texture_env_combine-combine')) if platform.system() != 'Windows': remove(join('glx', 'glx-multithread-shader-compile')) diff --git a/tests/quick.py b/tests/quick.py index c587357f6..5107d9fe4 100644 --- a/tests/quick.py +++ b/tests/quick.py @@ -63,6 +63,13 @@ with profile.test_list.group_manager( with profile.test_list.allow_reassignment: g(['arb_shader_image_size-builtin', '--quick'], 'builtin') +# Set the --quick flag on the texture env combine test +with profile.test_list.group_manager( + PiglitGLTest, + grouptools.join('spec', 'ext_texture_env_combine')) as g: + with profile.test_list.allow_reassignment: + g(['ext_texture_env_combine-combine', '--quick'], 'texture-env-combine') + # These take too long profile.filters.append(lambda n, _: '-explosion' not in n) profile.filters.append(FilterVsIn()) diff --git a/tests/spec/CMakeLists.txt b/tests/spec/CMakeLists.txt index f02c98ddc..44659d55f 100644 --- a/tests/spec/CMakeLists.txt +++ b/tests/spec/CMakeLists.txt @@ -90,6 +90,7 @@ add_subdirectory (ext_memory_object) add_subdirectory (ext_packed_depth_stencil) add_subdirectory (ext_packed_float) add_subdirectory (ext_shader_samples_identical) +add_subdirectory (ext_texture_env_combine) add_subdirectory (ext_texture_swizzle) add_subdirectory (ext_timer_query) add_subdirectory (ext_transform_feedback) diff --git a/tests/spec/ext_texture_env_combine/CMakeLists.gl.txt b/tests/spec/ext_texture_env_combine/CMakeLists.gl.txt new file mode 100644 index 000000000..3f5544289 --- /dev/null +++ b/tests/spec/ext_texture_env_combine/CMakeLists.gl.txt @@ -0,0 +1,11 @@ +include_directories( + ${GLEXT_INCLUDE_DIR} + ${OPENGL_INCLUDE_PATH} +) + +link_libraries ( + piglitutil_${piglit_target_api} + ${OPENGL_gl_LIBRARY} +) + +piglit_add_executable (ext_texture_env_combine-combine combine.c) diff --git a/tests/spec/ext_texture_env_combine/CMakeLists.txt b/tests/spec/ext_texture_env_combine/CMakeLists.txt new file mode 100644 index 000000000..144a306f4 --- /dev/null +++ b/tests/spec/ext_texture_env_combine/CMakeLists.txt @@ -0,0 +1 @@ +piglit_include_target_api() diff --git a/tests/spec/ext_texture_env_combine/combine.c b/tests/spec/ext_texture_env_combine/combine.c new file mode 100644 index 000000000..ca7cb0a00 --- /dev/null +++ b/tests/spec/ext_texture_env_combine/combine.c @@ -0,0 +1,1276 @@ +/* + * 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 combine.c: Test the GL_EXT_texture_env_combine extension + * Author: Brian Paul (brianp@valinux.com) September 2000 + * + * GL_EXT_texture_env_dot3 extension test + * Author: Gareth Hughes (gareth@valinux.com) January 2001 + * + * GL_ARB_texture_env_crossbar extension test + * Author: Brian Paul (brian@tungstengraphics.com) December 2002 + * + * The challenge with testing this extension is dealing with combinatorial + * explosion. There are 16 state variables in this extension: + * + * GL_COMBINE_RGB_EXT which has 5 possible values + * GL_COMBINE_ALPHA_EXT which has 5 possible values + * GL_SOURCE0_RGB_EXT which has 4 possible values + * GL_SOURCE1_RGB_EXT which has 4 possible values + * GL_SOURCE2_RGB_EXT which has 4 possible values + * GL_SOURCE0_ALPHA_EXT which has 4 possible values + * GL_SOURCE1_ALPHA_EXT which has 4 possible values + * GL_SOURCE2_ALPHA_EXT which has 4 possible values + * GL_OPERAND0_RGB_EXT which has 4 possible values + * GL_OPERAND1_RGB_EXT which has 4 possible values + * GL_OPERAND2_RGB_EXT which has 2 possible values + * GL_OPERAND0_ALPHA_EXT which has 2 possible values + * GL_OPERAND1_ALPHA_EXT which has 2 possible values + * GL_OPERAND2_ALPHA_EXT which has 1 possible value + * GL_RGB_SCALE_EXT which has 3 possible values + * GL_ALPHA_SCALE which has 3 possible values + * + * The product of those values is 117,964,800. And that's just for one + * texture unit! If we wanted to fully exercise N texture units we'd + * need to run 117,964,800 ^ N tests! Ideally we'd also like to test + * with a number of different fragment, texenv and texture colors. + * Clearly we can't test everything. + * + * So, we've partitioned the combination space into subsets defined + * by the replace_params[], add_params[], interpolate_params[], etc arrays. + * For multitexture, we do an even more limited set of tests: testing + * all permutations of the 5 combine modes on all texture units. + * + * In the future we might look at programs that use the combine + * extension to see which mode combination are important to them and + * put them into this test. + */ + +#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 = 2; + config.window_height = 2; + +PIGLIT_GL_TEST_CONFIG_END + +#define MAX_TEX_UNITS 8 + +#define COPY4(DST, SRC) \ +{ \ + (DST)[0] = (SRC)[0]; \ + (DST)[1] = (SRC)[1]; \ + (DST)[2] = (SRC)[2]; \ + (DST)[3] = (SRC)[3]; \ +} + +static bool have_dot3; +static bool have_crossbar; +static bool have_combine3; +static GLuint textures[MAX_TEX_UNITS]; +static int test_stride = 1; +static int num_tex_units; + +/* Our model of GL machine state */ +static struct { + GLenum COMBINE_RGB[MAX_TEX_UNITS]; + GLenum COMBINE_ALPHA[MAX_TEX_UNITS]; + GLenum SOURCE0_RGB[MAX_TEX_UNITS]; + GLenum SOURCE1_RGB[MAX_TEX_UNITS]; + GLenum SOURCE2_RGB[MAX_TEX_UNITS]; + GLenum SOURCE0_ALPHA[MAX_TEX_UNITS]; + GLenum SOURCE1_ALPHA[MAX_TEX_UNITS]; + GLenum SOURCE2_ALPHA[MAX_TEX_UNITS]; + GLenum OPERAND0_RGB[MAX_TEX_UNITS]; + GLenum OPERAND1_RGB[MAX_TEX_UNITS]; + GLenum OPERAND2_RGB[MAX_TEX_UNITS]; + GLenum OPERAND0_ALPHA[MAX_TEX_UNITS]; + GLenum OPERAND1_ALPHA[MAX_TEX_UNITS]; + GLenum OPERAND2_ALPHA[MAX_TEX_UNITS]; + float RGB_SCALE[MAX_TEX_UNITS]; + float ALPHA_SCALE[MAX_TEX_UNITS]; + float frag_color[4]; /* fragment color */ + float env_color[MAX_TEX_UNITS][4]; /* texture env color */ + float tex_color[MAX_TEX_UNITS][4]; /* texture image color */ + GLenum tex_format[MAX_TEX_UNITS]; /* texture base format */ +} machine; + +/* describes possible state combinations */ +struct test_param { + GLenum target; + GLenum valid_values[6]; +}; + +/* These objects define the space of tex-env combinations that we exercise. + * Each array element is { state-var, { list of possible values, 0 } }. + */ + +static const struct test_param replace_params[] = { + {GL_COMBINE_RGB_EXT, {GL_REPLACE, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_REPLACE, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 2, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 4, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param add_params[] = { + {GL_COMBINE_RGB_EXT, {GL_ADD, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_ADD, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 2, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 4, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param modulate_params[] = { + {GL_COMBINE_RGB_EXT, {GL_MODULATE, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_MODULATE, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 2, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 4, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param add_signed_params[] = { + {GL_COMBINE_RGB_EXT, {GL_ADD_SIGNED_EXT, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_ADD_SIGNED_EXT, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 2, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 4, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param interpolate_params[] = { + {GL_COMBINE_RGB_EXT, {GL_INTERPOLATE_EXT, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_INTERPOLATE_EXT, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_RGB_EXT, {GL_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_ALPHA_EXT, {GL_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param dot3_rgb_params[] = { + {GL_COMBINE_RGB_EXT, {GL_DOT3_RGB_EXT, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_MODULATE, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 2, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 4, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param dot3_rgba_params[] = { + {GL_COMBINE_RGB_EXT, {GL_DOT3_RGBA_EXT, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_MODULATE, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 2, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 4, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param modulate_add_params[] = { + {GL_COMBINE_RGB_EXT, {GL_MODULATE_ADD_ATI, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_MODULATE_ADD_ATI, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param modulate_signed_add_params[] = { + {GL_COMBINE_RGB_EXT, {GL_MODULATE_SIGNED_ADD_ATI, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_MODULATE_SIGNED_ADD_ATI, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static const struct test_param modulate_subtract_params[] = { + {GL_COMBINE_RGB_EXT, {GL_MODULATE_SUBTRACT_ATI, 0}}, + {GL_COMBINE_ALPHA_EXT, {GL_MODULATE_SUBTRACT_ATI, 0}}, + {GL_SOURCE0_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_RGB_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_RGB_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE0_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_SOURCE1_ALPHA_EXT, {GL_TEXTURE, GL_CONSTANT_EXT, GL_PRIMARY_COLOR_EXT, GL_PREVIOUS_EXT, 0}}, + {GL_SOURCE2_ALPHA_EXT, {GL_TEXTURE, GL_PRIMARY_COLOR_EXT, 0}}, + {GL_OPERAND0_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_RGB_EXT, {GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND0_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND1_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_OPERAND2_ALPHA_EXT, {GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, 0}}, + {GL_RGB_SCALE_EXT, {1, 4, 0}}, + {GL_ALPHA_SCALE, {1, 2, 0}}, + {0, {0, 0, 0, 0, 0}} +}; + +static void +problem(const char *s) +{ + fprintf(stderr, "Problem in combine(): %s\n", s); + assert(0); +} + +/* Set machine parameters to default values. */ +static void +reset_machine(void) +{ + for (int u = 0; u < MAX_TEX_UNITS; u++) { + machine.COMBINE_RGB[u] = GL_MODULATE; + machine.COMBINE_ALPHA[u] = GL_MODULATE; + machine.SOURCE0_RGB[u] = GL_TEXTURE; + machine.SOURCE1_RGB[u] = GL_PREVIOUS_EXT; + machine.SOURCE2_RGB[u] = GL_CONSTANT_EXT; + machine.SOURCE0_ALPHA[u] = GL_TEXTURE; + machine.SOURCE1_ALPHA[u] = GL_PREVIOUS_EXT; + machine.SOURCE2_ALPHA[u] = GL_CONSTANT_EXT; + machine.OPERAND0_RGB[u] = GL_SRC_COLOR; + machine.OPERAND1_RGB[u] = GL_SRC_COLOR; + machine.OPERAND2_RGB[u] = GL_SRC_ALPHA; + machine.OPERAND0_ALPHA[u] = GL_SRC_ALPHA; + machine.OPERAND1_ALPHA[u] = GL_SRC_ALPHA; + machine.OPERAND2_ALPHA[u] = GL_SRC_ALPHA; + machine.RGB_SCALE[u] = 1.0; + machine.ALPHA_SCALE[u] = 1.0; + machine.tex_format[u] = GL_RGBA; + } +} + +/* This computes the expected texcombine result for one texture unit. */ +static void +compute_tex_combine(int tex_unit, const float prev_color[4], float result[4]) +{ + float term0[4], term1[4], term2[4], dot; + const float *color_src0, *color_src1, *color_src2; + const float *alpha_src0, *alpha_src1 = NULL, *alpha_src2 = NULL; + const float *frag_color = machine.frag_color; + const float *const_color = machine.env_color[tex_unit]; + const float *tex_color = machine.tex_color[tex_unit]; + int src_unit; + + switch (machine.SOURCE0_RGB[tex_unit]) { + case GL_PRIMARY_COLOR_EXT: + color_src0 = frag_color; + break; + case GL_TEXTURE: + color_src0 = tex_color; + break; + case GL_CONSTANT_EXT: + color_src0 = const_color; + break; + case GL_PREVIOUS_EXT: + color_src0 = prev_color; + break; + case GL_TEXTURE0: + case GL_TEXTURE1: + case GL_TEXTURE2: + case GL_TEXTURE3: + case GL_TEXTURE4: + case GL_TEXTURE5: + case GL_TEXTURE6: + case GL_TEXTURE7: + /* GL_ARB_texture_env_crossbar */ + src_unit = machine.SOURCE0_RGB[tex_unit] - GL_TEXTURE0; + color_src0 = machine.tex_color[src_unit]; + break; + default: + problem("bad rgbSource0"); + return; + } + + switch (machine.SOURCE0_ALPHA[tex_unit]) { + case GL_PRIMARY_COLOR_EXT: + alpha_src0 = frag_color; + break; + case GL_TEXTURE: + alpha_src0 = tex_color; + break; + case GL_CONSTANT_EXT: + alpha_src0 = const_color; + break; + case GL_PREVIOUS_EXT: + alpha_src0 = prev_color; + break; + case GL_TEXTURE0: + case GL_TEXTURE1: + case GL_TEXTURE2: + case GL_TEXTURE3: + case GL_TEXTURE4: + case GL_TEXTURE5: + case GL_TEXTURE6: + case GL_TEXTURE7: + /* GL_ARB_texture_env_crossbar */ + src_unit = machine.SOURCE0_ALPHA[tex_unit] - GL_TEXTURE0; + alpha_src0 = machine.tex_color[src_unit]; + break; + default: + problem("bad alphaSource0"); + return; + } + + switch (machine.SOURCE1_RGB[tex_unit]) { + case GL_PRIMARY_COLOR_EXT: + color_src1 = frag_color; + break; + case GL_TEXTURE: + color_src1 = tex_color; + break; + case GL_CONSTANT_EXT: + color_src1 = const_color; + break; + case GL_PREVIOUS_EXT: + color_src1 = prev_color; + break; + case GL_TEXTURE0: + case GL_TEXTURE1: + case GL_TEXTURE2: + case GL_TEXTURE3: + case GL_TEXTURE4: + case GL_TEXTURE5: + case GL_TEXTURE6: + case GL_TEXTURE7: + /* GL_ARB_texture_env_crossbar */ + src_unit = machine.SOURCE1_RGB[tex_unit] - GL_TEXTURE0; + color_src1 = machine.tex_color[src_unit]; + break; + default: + problem("bad rgbSource1"); + return; + } + + switch (machine.SOURCE1_ALPHA[tex_unit]) { + case GL_PRIMARY_COLOR_EXT: + alpha_src1 = frag_color; + break; + case GL_TEXTURE: + alpha_src1 = tex_color; + break; + case GL_CONSTANT_EXT: + alpha_src1 = const_color; + break; + case GL_PREVIOUS_EXT: + alpha_src1 = prev_color; + break; + case GL_TEXTURE0: + case GL_TEXTURE1: + case GL_TEXTURE2: + case GL_TEXTURE3: + case GL_TEXTURE4: + case GL_TEXTURE5: + case GL_TEXTURE6: + case GL_TEXTURE7: + /* GL_ARB_texture_env_crossbar */ + src_unit = machine.SOURCE1_ALPHA[tex_unit] - GL_TEXTURE0; + alpha_src1 = machine.tex_color[src_unit]; + break; + default: + problem("bad alphaSource1"); + return; + } + + switch (machine.SOURCE2_RGB[tex_unit]) { + case GL_PRIMARY_COLOR_EXT: + color_src2 = frag_color; + break; + case GL_TEXTURE: + color_src2 = tex_color; + break; + case GL_CONSTANT_EXT: + color_src2 = const_color; + break; + case GL_PREVIOUS_EXT: + color_src2 = prev_color; + break; + case GL_TEXTURE0: + case GL_TEXTURE1: + case GL_TEXTURE2: + case GL_TEXTURE3: + case GL_TEXTURE4: + case GL_TEXTURE5: + case GL_TEXTURE6: + case GL_TEXTURE7: + /* GL_ARB_texture_env_crossbar */ + src_unit = machine.SOURCE2_RGB[tex_unit] - GL_TEXTURE0; + color_src2 = machine.tex_color[src_unit]; + break; + default: + problem("bad rgbSource2"); + return; + } + + switch (machine.SOURCE2_ALPHA[tex_unit]) { + case GL_PRIMARY_COLOR_EXT: + alpha_src2 = frag_color; + break; + case GL_TEXTURE: + alpha_src2 = tex_color; + break; + case GL_CONSTANT_EXT: + alpha_src2 = const_color; + break; + case GL_PREVIOUS_EXT: + alpha_src2 = prev_color; + break; + case GL_TEXTURE0: + case GL_TEXTURE1: + case GL_TEXTURE2: + case GL_TEXTURE3: + case GL_TEXTURE4: + case GL_TEXTURE5: + case GL_TEXTURE6: + case GL_TEXTURE7: + /* GL_ARB_texture_env_crossbar */ + src_unit = machine.SOURCE2_ALPHA[tex_unit] - GL_TEXTURE0; + alpha_src2 = machine.tex_color[src_unit]; + break; + default: + problem("bad alphaSource2"); + return; + } + + switch (machine.OPERAND0_RGB[tex_unit]) { + case GL_SRC_COLOR: + term0[0] = color_src0[0]; + term0[1] = color_src0[1]; + term0[2] = color_src0[2]; + break; + case GL_ONE_MINUS_SRC_COLOR: + term0[0] = 1.0 - color_src0[0]; + term0[1] = 1.0 - color_src0[1]; + term0[2] = 1.0 - color_src0[2]; + break; + case GL_SRC_ALPHA: + term0[0] = color_src0[3]; + term0[1] = color_src0[3]; + term0[2] = color_src0[3]; + break; + case GL_ONE_MINUS_SRC_ALPHA: + term0[0] = 1.0 - color_src0[3]; + term0[1] = 1.0 - color_src0[3]; + term0[2] = 1.0 - color_src0[3]; + break; + default: + problem("bad rgbOperand0"); + return; + } + + switch (machine.OPERAND0_ALPHA[tex_unit]) { + case GL_SRC_ALPHA: + term0[3] = alpha_src0[3]; + break; + case GL_ONE_MINUS_SRC_ALPHA: + term0[3] = 1.0 - alpha_src0[3]; + break; + default: + problem("bad alphaOperand0"); + return; + } + + switch (machine.OPERAND1_RGB[tex_unit]) { + case GL_SRC_COLOR: + term1[0] = color_src1[0]; + term1[1] = color_src1[1]; + term1[2] = color_src1[2]; + break; + case GL_ONE_MINUS_SRC_COLOR: + term1[0] = 1.0 - color_src1[0]; + term1[1] = 1.0 - color_src1[1]; + term1[2] = 1.0 - color_src1[2]; + break; + case GL_SRC_ALPHA: + term1[0] = color_src1[3]; + term1[1] = color_src1[3]; + term1[2] = color_src1[3]; + break; + case GL_ONE_MINUS_SRC_ALPHA: + term1[0] = 1.0 - color_src1[3]; + term1[1] = 1.0 - color_src1[3]; + term1[2] = 1.0 - color_src1[3]; + break; + default: + problem("bad rgbOperand1"); + return; + } + + switch (machine.OPERAND1_ALPHA[tex_unit]) { + case GL_SRC_ALPHA: + term1[3] = alpha_src1[3]; + break; + case GL_ONE_MINUS_SRC_ALPHA: + term1[3] = 1.0 - alpha_src1[3]; + break; + default: + problem("bad alphaOperand1"); + return; + } + + switch (machine.OPERAND2_RGB[tex_unit]) { + case GL_SRC_COLOR: + term2[0] = color_src2[0]; + term2[1] = color_src2[1]; + term2[2] = color_src2[2]; + break; + case GL_ONE_MINUS_SRC_COLOR: + term2[0] = 1.0 - color_src2[0]; + term2[1] = 1.0 - color_src2[1]; + term2[2] = 1.0 - color_src2[2]; + break; + case GL_SRC_ALPHA: + term2[0] = color_src2[3]; + term2[1] = color_src2[3]; + term2[2] = color_src2[3]; + break; + case GL_ONE_MINUS_SRC_ALPHA: + term2[0] = 1.0 - color_src2[3]; + term2[1] = 1.0 - color_src2[3]; + term2[2] = 1.0 - color_src2[3]; + break; + default: + problem("bad rgbOperand2"); + return; + } + + switch (machine.OPERAND2_ALPHA[tex_unit]) { + case GL_SRC_ALPHA: + term2[3] = alpha_src2[3]; + break; + default: + problem("bad alphaOperand2"); + return; + } + + /* Final combine */ + switch (machine.COMBINE_RGB[tex_unit]) { + case GL_REPLACE: + result[0] = term0[0]; + result[1] = term0[1]; + result[2] = term0[2]; + break; + case GL_MODULATE: + result[0] = term0[0] * term1[0]; + result[1] = term0[1] * term1[1]; + result[2] = term0[2] * term1[2]; + break; + case GL_ADD: + result[0] = term0[0] + term1[0]; + result[1] = term0[1] + term1[1]; + result[2] = term0[2] + term1[2]; + break; + case GL_ADD_SIGNED_EXT: + result[0] = term0[0] + term1[0] - 0.5; + result[1] = term0[1] + term1[1] - 0.5; + result[2] = term0[2] + term1[2] - 0.5; + break; + case GL_INTERPOLATE_EXT: + result[0] = term0[0] * term2[0] + term1[0] * (1.0 - term2[0]); + result[1] = term0[1] * term2[1] + term1[1] * (1.0 - term2[1]); + result[2] = term0[2] * term2[2] + term1[2] * (1.0 - term2[2]); + break; + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + dot = ((term0[0] - 0.5) * (term1[0] - 0.5) + + (term0[1] - 0.5) * (term1[1] - 0.5) + + (term0[2] - 0.5) * (term1[2] - 0.5)); + result[0] = dot; + result[1] = dot; + result[2] = dot; + if (machine.COMBINE_RGB[tex_unit] == GL_DOT3_RGBA_EXT) + result[3] = dot; + break; + case GL_MODULATE_ADD_ATI: + result[0] = term0[0] * term2[0] + term1[0]; + result[1] = term0[1] * term2[1] + term1[1]; + result[2] = term0[2] * term2[2] + term1[2]; + break; + case GL_MODULATE_SIGNED_ADD_ATI: + result[0] = term0[0] * term2[0] + term1[0] - 0.5; + result[1] = term0[1] * term2[1] + term1[1] - 0.5; + result[2] = term0[2] * term2[2] + term1[2] - 0.5; + break; + case GL_MODULATE_SUBTRACT_ATI: + result[0] = term0[0] * term2[0] - term1[0]; + result[1] = term0[1] * term2[1] - term1[1]; + result[2] = term0[2] * term2[2] - term1[2]; + break; + default: + problem("bad rgbCombine"); + return; + } + + switch (machine.COMBINE_ALPHA[tex_unit]) { + case GL_REPLACE: + result[3] = term0[3]; + break; + case GL_MODULATE: + result[3] = term0[3] * term1[3]; + break; + case GL_ADD: + result[3] = term0[3] + term1[3]; + break; + case GL_ADD_SIGNED_EXT: + result[3] = term0[3] + term1[3] - 0.5; + break; + case GL_INTERPOLATE_EXT: + result[3] = term0[3] * term2[3] + term1[3] * (1.0 - term2[3]); + break; + case GL_MODULATE_ADD_ATI: + result[3] = term0[3] * term2[3] + term1[3]; + break; + case GL_MODULATE_SIGNED_ADD_ATI: + result[3] = term0[3] * term2[3] + term1[3] - 0.5; + break; + case GL_MODULATE_SUBTRACT_ATI: + result[3] = term0[3] * term2[3] - term1[3]; + break; + default: + problem("bad alphaCombine"); + return; + } + + if (machine.COMBINE_RGB[tex_unit] == GL_DOT3_RGBA_EXT) { + result[3] = result[0]; + } + + /* scaling + * GH: Remove this crud when the ARB extension is done. It + * most likely won't have this scale factor restriction. */ + switch (machine.COMBINE_RGB[tex_unit]) { + case GL_DOT3_RGB_EXT: + case GL_DOT3_RGBA_EXT: + result[0] *= 4.0; + result[1] *= 4.0; + result[2] *= 4.0; + break; + default: + result[0] *= machine.RGB_SCALE[tex_unit]; + result[1] *= machine.RGB_SCALE[tex_unit]; + result[2] *= machine.RGB_SCALE[tex_unit]; + break; + } + switch (machine.COMBINE_RGB[tex_unit]) { + case GL_DOT3_RGBA_EXT: + result[3] *= 4.0; + break; + default: + result[3] *= machine.ALPHA_SCALE[tex_unit]; + break; + } + + /* final clamping */ + result[0] = CLAMP(result[0], 0.0, 1.0); + result[1] = CLAMP(result[1], 0.0, 1.0); + result[2] = CLAMP(result[2], 0.0, 1.0); + result[3] = CLAMP(result[3], 0.0, 1.0); +} + +/* Set the fragment, texenv (constant), and texture colors for all the + * machine's texture units. */ +static void +setup_colors(void) +{ + static const float frag_color[4] = {0.00, 0.25, 0.50, 0.75}; + static const float env_colors[][4] = {{0.25, 0.50, 0.75, 1.00}, + {0.50, 0.75, 1.00, 0.00}, + {0.75, 1.00, 0.00, 0.25}, + {1.00, 0.00, 0.25, 0.50}}; + static const float tex_colors[][8] = { + {1.00, 0.00, 0.25, 0.50}, + {0.75, 1.00, 0.00, 0.25}, + {0.50, 0.75, 1.00, 0.00}, + {0.25, 0.50, 0.75, 1.00}, + /* extra colors that'll only be used for crossbar test */ + {0.00, 0.00, 0.00, 0.00}, + {0.25, 0.50, 0.50, 0.00}, + {0.50, 0.25, 0.75, 0.25}, + {0.75, 1.00, 0.25, 0.00}}; + + COPY4(machine.frag_color, frag_color); + glColor4fv(frag_color); + + for (int u = 0; u < num_tex_units; u++) { + if (num_tex_units > 1) + glActiveTexture(GL_TEXTURE0 + u); + glBindTexture(GL_TEXTURE_2D, textures[u]); + glEnable(GL_TEXTURE_2D); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, + GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, + GL_NEAREST); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, + GL_COMBINE_EXT); + machine.env_color[u][0] = env_colors[u % 4][0]; + machine.env_color[u][1] = env_colors[u % 4][1]; + machine.env_color[u][2] = env_colors[u % 4][2]; + machine.env_color[u][3] = env_colors[u % 4][3]; + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, + env_colors[u % 4]); + + const float *tex_col = tex_colors[u % 8]; + + /* Setup texture color, according to texture format */ + switch (machine.tex_format[u]) { + case GL_RGBA: + machine.tex_color[u][0] = tex_col[0]; + machine.tex_color[u][1] = tex_col[1]; + machine.tex_color[u][2] = tex_col[2]; + machine.tex_color[u][3] = tex_col[3]; + break; + case GL_RGB: + machine.tex_color[u][0] = tex_col[0]; + machine.tex_color[u][1] = tex_col[1]; + machine.tex_color[u][2] = tex_col[2]; + machine.tex_color[u][3] = 1.0; + break; + case GL_ALPHA: + machine.tex_color[u][0] = 0.0; + machine.tex_color[u][1] = 0.0; + machine.tex_color[u][2] = 0.0; + machine.tex_color[u][3] = tex_col[3]; + break; + case GL_LUMINANCE: + machine.tex_color[u][0] = tex_col[0]; + machine.tex_color[u][1] = tex_col[0]; + machine.tex_color[u][2] = tex_col[0]; + machine.tex_color[u][3] = 1.0; + break; + case GL_LUMINANCE_ALPHA: + machine.tex_color[u][0] = tex_col[0]; + machine.tex_color[u][1] = tex_col[0]; + machine.tex_color[u][2] = tex_col[0]; + machine.tex_color[u][3] = tex_col[3]; + break; + case GL_INTENSITY: + machine.tex_color[u][0] = tex_col[0]; + machine.tex_color[u][1] = tex_col[0]; + machine.tex_color[u][2] = tex_col[0]; + machine.tex_color[u][3] = tex_col[0]; + break; + default: + problem("bad texture format"); + return; + } + + /* Make a 4x4 solid color texture */ + float image[16][4]; + for (int i = 0; i < 16; i++) { + image[i][0] = tex_colors[u % 8][0]; + image[i][1] = tex_colors[u % 8][1]; + image[i][2] = tex_colors[u % 8][2]; + image[i][3] = tex_colors[u % 8][3]; + } + glTexImage2D(GL_TEXTURE_2D, 0, machine.tex_format[u], 4, 4, 0, + GL_RGBA, GL_FLOAT, image); + } +} + +/* Examine a set of test params and compute the number of possible + * state combinations. */ +static int +count_test_combinations(const struct test_param test_params[]) +{ + int num_tests = 1; + for (int t = 0; test_params[t].target; t++) { + int values = 0; + for (int val = 0; test_params[t].valid_values[val]; val++) { + values++; + } + num_tests *= values; + } + return num_tests / test_stride; +} + +/* Setup the actual GL state and our internal simulated GL state. */ +static void +tex_env(int tex_unit, GLenum target, GLenum value) +{ + if (num_tex_units > 1) + glActiveTexture(GL_TEXTURE0 + tex_unit); + + glTexEnvi(GL_TEXTURE_ENV, target, value); + piglit_check_gl_error(GL_NO_ERROR); + + switch (target) { + case GL_COMBINE_RGB_EXT: + machine.COMBINE_RGB[tex_unit] = value; + break; + case GL_COMBINE_ALPHA_EXT: + machine.COMBINE_ALPHA[tex_unit] = value; + break; + case GL_SOURCE0_RGB_EXT: + machine.SOURCE0_RGB[tex_unit] = value; + break; + case GL_SOURCE1_RGB_EXT: + machine.SOURCE1_RGB[tex_unit] = value; + break; + case GL_SOURCE2_RGB_EXT: + machine.SOURCE2_RGB[tex_unit] = value; + break; + case GL_SOURCE0_ALPHA_EXT: + machine.SOURCE0_ALPHA[tex_unit] = value; + break; + case GL_SOURCE1_ALPHA_EXT: + machine.SOURCE1_ALPHA[tex_unit] = value; + break; + case GL_SOURCE2_ALPHA_EXT: + machine.SOURCE2_ALPHA[tex_unit] = value; + break; + case GL_OPERAND0_RGB_EXT: + machine.OPERAND0_RGB[tex_unit] = value; + break; + case GL_OPERAND1_RGB_EXT: + machine.OPERAND1_RGB[tex_unit] = value; + break; + case GL_OPERAND2_RGB_EXT: + machine.OPERAND2_RGB[tex_unit] = value; + break; + case GL_OPERAND0_ALPHA_EXT: + machine.OPERAND0_ALPHA[tex_unit] = value; + break; + case GL_OPERAND1_ALPHA_EXT: + machine.OPERAND1_ALPHA[tex_unit] = value; + break; + case GL_OPERAND2_ALPHA_EXT: + machine.OPERAND2_ALPHA[tex_unit] = value; + break; + case GL_RGB_SCALE_EXT: + machine.RGB_SCALE[tex_unit] = value; + break; + case GL_ALPHA_SCALE: + machine.ALPHA_SCALE[tex_unit] = value; + break; + } +} + +/* Make the glTexEnv calls to setup one particular set of test parameters + * from <test_params>. + * <test_num> must be between 0 and count_test_combinations(test_params)-1. */ +static void +setup_test_env(int test_num, const struct test_param test_params[]) +{ + int divisor = 1; + for (int t = 0; test_params[t].target; t++) { + int num_values = 0; + for (int val = 0; test_params[t].valid_values[val]; val++) { + num_values++; + } + assert(num_values > 0); + int v = (test_num / divisor) % num_values; + GLenum target = test_params[t].target; + GLenum value = test_params[t].valid_values[v]; + tex_env(0, target, value); + divisor *= num_values; + } +} + +static void +print_test_env(int test_num, const struct test_param test_params[]) +{ + int divisor = 1; + for (int t = 0; test_params[t].target; t++) { + int num_values = 0; + for (int val = 0; test_params[t].valid_values[val]; val++) { + num_values++; + } + assert(num_values > 0); + int v = (test_num / divisor) % num_values; + GLenum target = test_params[t].target; + GLenum value = test_params[t].valid_values[v]; + printf("%s %s\n", piglit_get_gl_enum_name(target), + piglit_get_gl_enum_name(value)); + divisor *= num_values; + } + printf("\n"); +} + +#define RUN_SINGLE_TEXTURE_TEST(test) run_single_texture_test(test, #test) + +/* Test texenv-combine with a single texture unit. */ +static bool +run_single_texture_test(const struct test_param test_params[], + const char *test_name) +{ + assert(num_tex_units == 1); + setup_colors(); + + const int num_tests = count_test_combinations(test_params); + + for (int test = 0; test < num_tests; test += test_stride) { + /* 0. Setup state */ + reset_machine(); + setup_test_env(test, test_params); + + /* 1. Render with OpenGL */ + glTexCoord2f(0, 0); /* use texcoord (0,0) for all vertices */ + piglit_draw_rect(-1, -1, 2, 2); + + /* 2. Compute expected result */ + float expected[4]; + expected[3] = -1.0f; + compute_tex_combine(0, machine.frag_color, expected); + + /* 3. Compare rendered result to expected result */ + if (!piglit_probe_pixel_rgba(0, 0, expected)) { + printf("Single Texture Test %s %d\n", test_name, + test); + print_test_env(test, test_params); + return false; + } + } + return true; +} + +/* For each texture unit, test each texenv-combine mode. + * That's 5 ^ num_tex_units combinations. + * Or 7 ^ num_tex_units if DOT3 combine mode is supported */ +static int +count_multi_texture_test_combinations() +{ + int num_tests = 1; + for (int i = 0; i < num_tex_units; i++) + num_tests *= (have_dot3 ? 7 : 5); + + return num_tests / test_stride; +} + +/* Test texenv-combine with multiple texture units. */ +static bool +run_multi_texture_test(void) +{ + static const GLenum combine_modes[10] = { + GL_REPLACE, + GL_ADD, + GL_ADD_SIGNED_EXT, + GL_MODULATE, + GL_INTERPOLATE_EXT, + GL_DOT3_RGB_EXT, + GL_DOT3_RGBA_EXT, + GL_MODULATE_ADD_ATI, + GL_MODULATE_SIGNED_ADD_ATI, + GL_MODULATE_SUBTRACT_ATI + }; + const int num_modes = have_dot3 ? (have_combine3 ? 10 : 7) : 5; + + /* four texture units is enough to test */ + if (num_tex_units > 4) + num_tex_units = 4; + + const int num_tests = count_multi_texture_test_combinations(); + + setup_colors(); + for (int test_num = 0; test_num < num_tests; + test_num += test_stride) { + /* 0. Set up texture units */ + reset_machine(); + int divisor = 1; + for (int u = 0; u < num_tex_units; u++) { + const int m = (test_num / divisor) % num_modes; + const GLenum mode = combine_modes[m]; + + /* Set GL_COMBINE_RGB_EXT and GL_COMBINE_ALPHA_EXT */ + tex_env(u, GL_COMBINE_RGB_EXT, mode); + tex_env(u, GL_COMBINE_ALPHA_EXT, + (mode == GL_DOT3_RGB_EXT || + mode == GL_DOT3_RGBA_EXT) + ? GL_REPLACE + : mode); + tex_env(u, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + tex_env(u, GL_SOURCE1_RGB_EXT, GL_PREVIOUS_EXT); + tex_env(u, GL_SOURCE2_RGB_EXT, GL_TEXTURE); + tex_env(u, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + tex_env(u, GL_SOURCE1_ALPHA_EXT, GL_PREVIOUS_EXT); + tex_env(u, GL_SOURCE2_ALPHA_EXT, GL_TEXTURE); + tex_env(u, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); + tex_env(u, GL_OPERAND1_RGB_EXT, + GL_ONE_MINUS_SRC_COLOR); + tex_env(u, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); + tex_env(u, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + tex_env(u, GL_OPERAND1_ALPHA_EXT, + GL_ONE_MINUS_SRC_ALPHA); + tex_env(u, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA); + tex_env(u, GL_RGB_SCALE_EXT, 1); + tex_env(u, GL_ALPHA_SCALE, 1); + + divisor *= num_modes; + } + + /* 1. Render with OpenGL */ + /* use texcoord (0,0) for all vertices */ + for (int u = 0; u < num_tex_units; u++) + glMultiTexCoord2f(GL_TEXTURE0 + u, 0, 0); + piglit_draw_rect(-1, -1, 2, 2); + + /* 2. Compute expected result */ + float prev_color[4]; + float expected[4] = {0}; + COPY4(prev_color, machine.frag_color); + for (int u = 0; u < num_tex_units; u++) { + compute_tex_combine(u, prev_color, expected); + COPY4(prev_color, expected); + } + + /* 3. Compare rendered result to expected result */ + if (!piglit_probe_pixel_rgba(0, 0, expected)) { + printf("Multi-texture test %d\n", test_num); + return false; + } + } + return true; +} + +/* We do a really short, simple test for GL_ARB_texture_env_crossbar since the + * preceeding tests are pretty comprehensive and the crossbar feature is just + * an incremental addition. Basically, if we have N texture units we run N + * tests. For test [i] we set texture unit [i] to fetch the texture color + * from unit [num_units - i - 1]. For units != i we use the constant color + * (0,0,0,0). We use GL_ADD mode to compute the sum over all units. So + * effectively, the result of texture combine is simply the incoming fragment + * color plus unit [num_units - test - 1]'s texture color. */ +static bool +run_crossbar_test() +{ + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &num_tex_units); + + /* Set up constant texture state for all tests */ + setup_colors(); + reset_machine(); + for (int unit = 0; unit < num_tex_units; unit++) { + tex_env(unit, GL_COMBINE_RGB_EXT, GL_ADD); + tex_env(unit, GL_COMBINE_ALPHA_EXT, GL_ADD); + tex_env(unit, GL_SOURCE0_RGB_EXT, GL_PREVIOUS_EXT); + tex_env(unit, GL_SOURCE0_ALPHA_EXT, GL_PREVIOUS_EXT); + /* SOURCE1_RGB/ALPHA is set below, per test */ + tex_env(unit, GL_OPERAND0_RGB_EXT, GL_SRC_COLOR); + tex_env(unit, GL_OPERAND1_RGB_EXT, GL_SRC_COLOR); + tex_env(unit, GL_OPERAND2_RGB_EXT, GL_SRC_ALPHA); + tex_env(unit, GL_OPERAND0_ALPHA_EXT, GL_SRC_ALPHA); + tex_env(unit, GL_OPERAND1_ALPHA_EXT, GL_SRC_ALPHA); + tex_env(unit, GL_OPERAND2_ALPHA_EXT, GL_SRC_ALPHA); + tex_env(unit, GL_RGB_SCALE_EXT, 1); + tex_env(unit, GL_ALPHA_SCALE, 1); + + machine.env_color[unit][0] = 0.0; + machine.env_color[unit][1] = 0.0; + machine.env_color[unit][2] = 0.0; + machine.env_color[unit][3] = 0.0; + glActiveTexture(GL_TEXTURE0 + unit); + glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, + machine.env_color[unit]); + } + + for (int test = 0; test < num_tex_units; test++) { + /* 1. Set up texture state */ + for (int unit = 0; unit < num_tex_units; unit++) { + if (unit == test) { + const int revUnit = num_tex_units - unit - 1; + tex_env(unit, GL_SOURCE1_RGB_EXT, + GL_TEXTURE0 + revUnit); + tex_env(unit, GL_SOURCE1_ALPHA_EXT, + GL_TEXTURE0 + revUnit); + } else { + tex_env(unit, GL_SOURCE1_RGB_EXT, + GL_CONSTANT_EXT); + tex_env(unit, GL_SOURCE1_ALPHA_EXT, + GL_CONSTANT_EXT); + } + } + + /* 2. Render with OpenGL */ + /* texcoord (0,) for all vertices is OK */ + for (int unit = 0; unit < num_tex_units; unit++) + glMultiTexCoord2f(GL_TEXTURE0 + unit, 0, 0); + piglit_draw_rect(-1, -1, 2, 2); + + /* 3. Compute expected result */ + float prev_color[4]; + float expected[4]; + COPY4(prev_color, machine.frag_color); + for (int unit = 0; unit < num_tex_units; unit++) { + compute_tex_combine(unit, prev_color, expected); + COPY4(prev_color, expected); + } + + /* 4. Compare rendered result to expected result */ + if (!piglit_probe_pixel_rgba(0, 0, expected)) { + printf("Texture crossbar test %d\n", test); + return false; + } + } + return true; +} + +enum piglit_result +piglit_display(void) +{ + bool pass = true; + float old_tolerance[4]; + + /* Do single texture unit tests first. */ + if (pass) + pass = RUN_SINGLE_TEXTURE_TEST(replace_params); + if (pass) + pass = RUN_SINGLE_TEXTURE_TEST(add_params); + if (pass) + pass = RUN_SINGLE_TEXTURE_TEST(add_signed_params); + if (pass) + pass = RUN_SINGLE_TEXTURE_TEST(modulate_params); + if (pass) + pass = RUN_SINGLE_TEXTURE_TEST(interpolate_params); + /* Some implementations have precision problems with the dot3 + * instruction. */ + for (int i = 0; i < 4; ++i) { + old_tolerance[i] = piglit_tolerance[i]; + piglit_tolerance[i] = MAX2(0.02, piglit_tolerance[i]); + } + if (pass && have_dot3) + pass = RUN_SINGLE_TEXTURE_TEST(dot3_rgb_params); + if (pass && have_dot3) + pass = RUN_SINGLE_TEXTURE_TEST(dot3_rgba_params); + for (int i = 0; i < 4; ++i) + piglit_tolerance[i] = old_tolerance[i]; + if (pass && have_combine3) + pass = RUN_SINGLE_TEXTURE_TEST(modulate_add_params); + if (pass && have_combine3) + pass = RUN_SINGLE_TEXTURE_TEST(modulate_signed_add_params); + if (pass && have_combine3) + pass = RUN_SINGLE_TEXTURE_TEST(modulate_subtract_params); + + /* Now do some multi-texture tests */ + glGetIntegerv(GL_MAX_TEXTURE_UNITS, &num_tex_units); + if (pass && num_tex_units > 1) { + pass = run_multi_texture_test(); + } + + /* Do crossbar tests */ + if (pass && have_crossbar) { + pass = run_crossbar_test(); + } + + return pass ? PIGLIT_PASS : PIGLIT_FAIL; +} + +void +piglit_init(int argc, char **argv) +{ + piglit_require_extension("GL_EXT_texture_env_combine"); + + /* Test the availability of the DOT3 extenstion */ + have_dot3 = piglit_is_extension_supported("GL_EXT_texture_env_dot3"); + + have_crossbar = + piglit_is_extension_supported("GL_ARB_texture_env_crossbar"); + + have_combine3 = + piglit_is_extension_supported("GL_ATI_texture_env_combine3"); + + /* Allocate our textures */ + glGenTextures(MAX_TEX_UNITS, textures); + + reset_machine(); + num_tex_units = 1; + + for (int i = 1; i < argc; i++) + if (!strcmp(argv[i], "--quick")) + test_stride = 67; /* a prime number */ +} |