fp-indirections2: Do a single readpixels per dim rather than 32*32 RGB probes.
[piglit.git] / tests / shaders / fp-indirections2.c
blob04c703befedfdbc5ca463c52a8ac7019e358090f
1 /*
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
13 * Software.
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
21 * IN THE SOFTWARE.
23 * Authors:
24 * Nicolai Hähnle <nhaehnle@gmail.com>
28 /**
29 * \file
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)
55 unsigned int x, y, z;
56 unsigned char *p;
57 unsigned char *q;
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);
64 p = texture_data;
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();
70 p[0] = r & 31;
71 p[1] = (r >> 5) & 31;
72 p[2] = (r >> 10) & 31;
74 q[0] = p[0] * 8 + 4;
75 q[1] = p[1] * 8 + 4;
76 q[2] = p[2] * 8 + 4;
77 q[3] = 0xff;
79 p += 3;
80 q += 4;
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(
104 unsigned int dim,
105 unsigned int x, unsigned int y, unsigned int z,
106 unsigned int hops,
107 float * expected)
109 unsigned int i;
111 for(i = 0; i < hops; ++i) {
112 unsigned char * p;
114 if (dim < 3)
115 z = 0;
116 if (dim < 2)
117 y = 0;
119 p = texture_data + z*TEXTURE_SIZE*TEXTURE_SIZE*3 + y*TEXTURE_SIZE*3 + x*3;
120 x = p[0];
121 y = p[1];
122 z = p[2];
125 expected[0] = (x + 0.5) / 32.0;
126 expected[1] = (y + 0.5) / 32.0;
127 expected[2] = (z + 0.5) / 32.0;
129 if (!hops)
130 expected[2] = 0.0;
133 static const char program_Head[] =
134 "!!ARBfp1.0\n"
135 "TEMP r;\n"
138 static const char program_TEX[] =
139 "TEX %s, %s, texture[0], %iD;\n";
141 static const char program_MOV[] =
142 "MOV %s, %s;\n";
144 static const char program_Tail[] =
145 "END\n";
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));
156 char buf[128];
157 GLuint program_object;
158 unsigned int draw_height;
159 unsigned int x, y;
161 strcpy(program_text, program_Head);
162 if (!samples) {
163 snprintf(buf, sizeof(buf), program_MOV, program_Output, program_Input);
164 strcat(program_text, buf);
165 } else {
166 const char * input = program_Input;
167 unsigned int i;
168 for(i = 1; i <= samples; ++i) {
169 const char * output = "r";
170 if (i == samples)
171 output = program_Output;
172 snprintf(buf, sizeof(buf), program_TEX, output, input, dim);
173 strcat(program_text, buf);
174 input = output;
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);
190 free(program_text);
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) {
197 float expected[3];
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);
203 free(pixels);
204 return PIGLIT_FAIL;
209 free(pixels);
211 return PIGLIT_PASS;
214 enum piglit_result
215 piglit_display(void)
217 enum piglit_result result;
218 unsigned int dim;
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) {
228 samples = 0;
229 for(;;) {
230 printf("Test dim %d samples %d\n", dim, samples);
231 result = test(dim, samples);
232 if (result != PIGLIT_PASS)
233 return result;
235 if (samples < 8) {
236 samples++;
237 } else if (samples < max_samples) {
238 samples *= 2;
239 if (samples > max_samples)
240 samples = max_samples;
241 } else {
242 break;
247 return PIGLIT_PASS;
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
274 * count.
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)
281 max_samples = 256;
283 texture_init();