2 * Copyright (c) 2009 Nicolai Hähnle
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Nicolai Hähnle <nhaehnle@gmail.com>
30 * Whereas fp-indirections tests that the native indirection limits are
31 * reported essentially correctly, this test actually exercises multiple
32 * indirection counts up to the reported native limit.
35 #include "piglit-util-gl.h"
37 #define TEXTURE_SIZE 32 /* Note: Hardcoded dependencies in texture_init and texture_follow */
39 PIGLIT_GL_TEST_CONFIG_BEGIN
41 config
.supports_gl_compat_version
= 10;
43 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
;
45 PIGLIT_GL_TEST_CONFIG_END
47 unsigned int max_samples
;
48 unsigned char * texture_data
;
49 unsigned char * texture_data_as_rgba
;
50 GLuint texture_objects
[3];
53 static void texture_init(void)
59 srand(0x12345678); /* we want repeatable test runs */
61 texture_data
= malloc(TEXTURE_SIZE
* TEXTURE_SIZE
* TEXTURE_SIZE
* 3);
62 texture_data_as_rgba
= malloc(TEXTURE_SIZE
* TEXTURE_SIZE
* TEXTURE_SIZE
* 4);
65 q
= texture_data_as_rgba
;
66 for(z
= 0; z
< TEXTURE_SIZE
; ++z
) {
67 for(y
= 0; y
< TEXTURE_SIZE
; ++y
) {
68 for(x
= 0; x
< TEXTURE_SIZE
; ++x
) {
69 unsigned int r
= rand();
72 p
[2] = (r
>> 10) & 31;
85 glGenTextures(3, texture_objects
);
87 glBindTexture(GL_TEXTURE_1D
, texture_objects
[0]);
88 glTexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
89 glTexParameteri(GL_TEXTURE_1D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
90 glTexImage1D(GL_TEXTURE_1D
, 0, GL_RGB
, TEXTURE_SIZE
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, texture_data_as_rgba
);
92 glBindTexture(GL_TEXTURE_2D
, texture_objects
[1]);
93 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
94 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
95 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGB
, TEXTURE_SIZE
, TEXTURE_SIZE
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, texture_data_as_rgba
);
97 glBindTexture(GL_TEXTURE_3D
, texture_objects
[2]);
98 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
99 glTexParameteri(GL_TEXTURE_3D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
100 glTexImage3D(GL_TEXTURE_3D
, 0, GL_RGB
, TEXTURE_SIZE
, TEXTURE_SIZE
, TEXTURE_SIZE
, 0, GL_RGBA
, GL_UNSIGNED_BYTE
, texture_data_as_rgba
);
103 static void texture_follow(
105 unsigned int x
, unsigned int y
, unsigned int z
,
111 for(i
= 0; i
< hops
; ++i
) {
119 p
= texture_data
+ z
*TEXTURE_SIZE
*TEXTURE_SIZE
*3 + y
*TEXTURE_SIZE
*3 + x
*3;
125 expected
[0] = (x
+ 0.5) / 32.0;
126 expected
[1] = (y
+ 0.5) / 32.0;
127 expected
[2] = (z
+ 0.5) / 32.0;
133 static const char program_Head
[] =
138 static const char program_TEX
[] =
139 "TEX %s, %s, texture[0], %iD;\n";
141 static const char program_MOV
[] =
144 static const char program_Tail
[] =
147 static const char program_Input
[] = "fragment.texcoord[0]";
148 static const char program_Output
[] = "result.color";
150 static enum piglit_result
test(unsigned int dim
, unsigned int samples
)
152 char * program_text
= malloc(sizeof(program_Head
) +
153 (samples
+ 1)*sizeof(program_TEX
) +
154 sizeof(program_Tail
) +
155 sizeof(program_Input
) + sizeof(program_Output
));
157 GLuint program_object
;
158 unsigned int draw_height
;
161 strcpy(program_text
, program_Head
);
163 snprintf(buf
, sizeof(buf
), program_MOV
, program_Output
, program_Input
);
164 strcat(program_text
, buf
);
166 const char * input
= program_Input
;
168 for(i
= 1; i
<= samples
; ++i
) {
169 const char * output
= "r";
171 output
= program_Output
;
172 snprintf(buf
, sizeof(buf
), program_TEX
, output
, input
, dim
);
173 strcat(program_text
, buf
);
177 strcat(program_text
, program_Tail
);
179 program_object
= piglit_compile_program(GL_FRAGMENT_PROGRAM_ARB
, program_text
);
181 glEnable(GL_FRAGMENT_PROGRAM_ARB
);
182 glBindProgramARB(GL_FRAGMENT_PROGRAM_ARB
, program_object
);
184 draw_height
= TEXTURE_SIZE
;
185 piglit_draw_rect_tex(0, 0, TEXTURE_SIZE
, draw_height
, 0, 0, 1, 1);
187 glDisable(GL_FRAGMENT_PROGRAM_ARB
);
188 glDeleteProgramsARB(1, &program_object
);
192 float *pixels
= malloc(draw_height
* TEXTURE_SIZE
* 3 * sizeof(float));
193 glReadPixels(0, 0, TEXTURE_SIZE
, draw_height
, GL_RGB
, GL_FLOAT
, pixels
);
195 for(y
= 0; y
< draw_height
; ++y
) {
196 for(x
= 0; x
< TEXTURE_SIZE
; ++x
) {
198 texture_follow(dim
, x
, y
, 0, samples
, expected
);
199 if (!piglit_compare_pixels(x
, y
, expected
,
200 pixels
+ (y
* TEXTURE_SIZE
+ x
) * 3,
201 piglit_tolerance
, 3)) {
202 fprintf(stderr
, "Failure in dim = %i, samples = %i\n", dim
, samples
);
217 enum piglit_result result
;
219 unsigned int samples
;
221 assert(piglit_width
>= TEXTURE_SIZE
);
222 assert(piglit_height
>= TEXTURE_SIZE
);
224 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
225 glClear(GL_COLOR_BUFFER_BIT
);
227 for(dim
= 1; dim
<= 3; ++dim
) {
230 printf("Test dim %d samples %d\n", dim
, samples
);
231 result
= test(dim
, samples
);
232 if (result
!= PIGLIT_PASS
)
237 } else if (samples
< max_samples
) {
239 if (samples
> max_samples
)
240 samples
= max_samples
;
251 void piglit_init(int argc
, char ** argv
)
253 GLint max_native_tex_instructions
;
254 GLint max_native_tex_indirections
;
256 piglit_require_fragment_program();
258 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
,
259 GL_MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB
,
260 &max_native_tex_instructions
);
261 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB
,
262 GL_MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB
,
263 &max_native_tex_indirections
);
265 printf("Max TEX instructions / TEX indirections: %i / %i\n",
266 max_native_tex_instructions
,
267 max_native_tex_indirections
);
269 max_samples
= max_native_tex_indirections
;
270 if (max_samples
> max_native_tex_instructions
) {
271 /* ARB_fragment_program, issue 24:
272 * For implementations with no restrictions on the number of indirections,
273 * the maximum indirection count will equal the maximum texture instruction
276 fprintf(stderr
, "Violation of ARB_fragment_program issue 24: TEX indirections > TEX instructions\n");
277 max_samples
= max_native_tex_instructions
;
280 if (max_samples
> 256)