2 * Copyright (C) 1999 Allen Akin All Rights Reserved.
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or
9 * sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
18 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
19 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
20 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL ALLEN AKIN BE
21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
23 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
24 * DEALINGS IN THE SOFTWARE.
29 * @file combine.c: Test GL_NV_texture_env_combine4
30 * Author: Brian Paul (brianp@valinux.com) January 2009
32 * Generate some random combiner state and colors, compute the expected
33 * color, then render with the combiner state and compare the results.
34 * Only one texture unit is tested and not all possible combiner terms
38 #include "piglit-util-gl.h"
40 PIGLIT_GL_TEST_CONFIG_BEGIN
42 config
.supports_gl_compat_version
= 13;
43 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
;
44 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
46 PIGLIT_GL_TEST_CONFIG_END
49 #define SRAND(x) srand(x)
50 #define DRAND() ((float)rand() / RAND_MAX)
52 #define SRAND(x) srand48(x)
53 #define DRAND() drand48()
58 struct combine_state
{
61 GLenum operand_rgb
[4];
63 float primary_color
[4];
64 float constant_color
[4];
65 float texture_color
[4];
68 /* generate random combiner state */
70 generate_state(struct combine_state
*state
)
73 state
->combine_mode
= GL_ADD
;
75 state
->combine_mode
= GL_ADD_SIGNED_EXT
;
77 for (int i
= 0; i
< 4; i
++) {
78 int src
= (int)(DRAND() * 4.0);
81 state
->source
[i
] = GL_ZERO
;
84 state
->source
[i
] = GL_TEXTURE
;
87 state
->source
[i
] = GL_CONSTANT_EXT
;
90 state
->source
[i
] = GL_PRIMARY_COLOR_EXT
;
95 state
->operand_rgb
[i
] = GL_SRC_COLOR
;
96 state
->operand_a
[i
] = GL_SRC_ALPHA
;
98 state
->operand_rgb
[i
] = GL_ONE_MINUS_SRC_COLOR
;
99 state
->operand_a
[i
] = GL_ONE_MINUS_SRC_ALPHA
;
103 state
->primary_color
[0] = DRAND();
104 state
->primary_color
[1] = DRAND();
105 state
->primary_color
[2] = DRAND();
106 state
->primary_color
[3] = DRAND();
108 state
->constant_color
[0] = DRAND();
109 state
->constant_color
[1] = DRAND();
110 state
->constant_color
[2] = DRAND();
111 state
->constant_color
[3] = DRAND();
113 state
->texture_color
[0] = DRAND();
114 state
->texture_color
[1] = DRAND();
115 state
->texture_color
[2] = DRAND();
116 state
->texture_color
[3] = DRAND();
119 /* compute expected final color */
121 evaluate_state(const struct combine_state state
, float result
[4])
126 for (int i
= 0; i
< 4; i
++) {
127 switch (state
.source
[i
]) {
129 arg
[i
][0] = arg
[i
][1] = arg
[i
][2] = arg
[i
][3] = 0.0f
;
131 case GL_PRIMARY_COLOR_EXT
:
132 arg
[i
][0] = state
.primary_color
[0];
133 arg
[i
][1] = state
.primary_color
[1];
134 arg
[i
][2] = state
.primary_color
[2];
135 arg
[i
][3] = state
.primary_color
[3];
137 case GL_CONSTANT_EXT
:
138 arg
[i
][0] = state
.constant_color
[0];
139 arg
[i
][1] = state
.constant_color
[1];
140 arg
[i
][2] = state
.constant_color
[2];
141 arg
[i
][3] = state
.constant_color
[3];
144 arg
[i
][0] = state
.texture_color
[0];
145 arg
[i
][1] = state
.texture_color
[1];
146 arg
[i
][2] = state
.texture_color
[2];
147 arg
[i
][3] = state
.texture_color
[3];
153 switch (state
.operand_rgb
[i
]) {
157 case GL_ONE_MINUS_SRC_COLOR
:
158 arg
[i
][0] = 1.0f
- arg
[i
][0];
159 arg
[i
][1] = 1.0f
- arg
[i
][1];
160 arg
[i
][2] = 1.0f
- arg
[i
][2];
161 arg
[i
][3] = 1.0f
- arg
[i
][3];
168 /* combine terms, loop over color channels */
169 for (int i
= 0; i
< 4; i
++) {
170 result
[i
] = arg
[0][i
] * arg
[1][i
] + arg
[2][i
] * arg
[3][i
];
171 if (state
.combine_mode
== GL_ADD_SIGNED_EXT
)
173 if (result
[i
] < 0.0f
)
175 else if (result
[i
] > 1.0f
)
180 /* render quad with given combiner state and compare resulting color
181 * return false if GL error is detected or comparison fails, true otherwise.
184 render_state(const struct combine_state state
, const float expected
[4])
186 if (!piglit_check_gl_error(GL_NO_ERROR
))
189 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE4_NV
);
191 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB
, state
.combine_mode
);
192 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA
, state
.combine_mode
);
194 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_RGB
, state
.source
[0]);
195 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE0_ALPHA
, state
.source
[0]);
196 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_RGB
, state
.source
[1]);
197 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE1_ALPHA
, state
.source
[1]);
198 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_RGB
, state
.source
[2]);
199 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE2_ALPHA
, state
.source
[2]);
200 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_RGB_NV
, state
.source
[3]);
201 glTexEnvi(GL_TEXTURE_ENV
, GL_SOURCE3_ALPHA_NV
, state
.source
[3]);
203 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_RGB
, state
.operand_rgb
[0]);
204 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND0_ALPHA
, state
.operand_a
[0]);
205 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_RGB
, state
.operand_rgb
[1]);
206 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND1_ALPHA
, state
.operand_a
[1]);
207 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_RGB
, state
.operand_rgb
[2]);
208 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND2_ALPHA
, state
.operand_a
[2]);
209 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_RGB_NV
, state
.operand_rgb
[3]);
210 glTexEnvi(GL_TEXTURE_ENV
, GL_OPERAND3_ALPHA_NV
, state
.operand_a
[3]);
212 glTexEnvfv(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_COLOR
,
213 state
.constant_color
);
215 if (!piglit_check_gl_error(GL_NO_ERROR
))
218 glEnable(GL_TEXTURE_2D
);
219 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
220 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
222 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA
, 1, 1, 0, GL_RGBA
, GL_FLOAT
,
223 state
.texture_color
);
225 glColor4fv(state
.primary_color
);
227 glClear(GL_COLOR_BUFFER_BIT
);
228 piglit_draw_rect_tex(-1, -1, 2, 2, 0, 0, 1, 1);
230 return piglit_probe_pixel_rgb(piglit_width
/ 2, piglit_height
/ 2,
237 for (int i
= 0; i
< NUM_TESTS
; i
++) {
238 struct combine_state state
;
241 generate_state(&state
);
243 evaluate_state(state
, expected
);
245 if (!render_state(state
, expected
))
253 piglit_init(int argc
, char **argv
)
255 piglit_require_extension("GL_NV_texture_env_combine4");
256 SRAND(42); /* init random number generator */