1 /*
2  * Copyright (c) 2010 VMware, Inc.
3  *
4  * Permission is hereby , 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:
10  *
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.
14  *
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.
22  *
23  *
24  * Test GL_EXT_texture_array and GL_MESA_texture_array.
25  * Note that the Mesa extension works with fixed-function fragment
26  * processing whereas the EXT version only works with shaders.
27  *
28  * Author: Brian Paul
29  */
30 
31 
32 #include "piglit-util-gl.h"
33 
34 PIGLIT_GL_TEST_CONFIG_BEGIN
35 
36 	config.supports_gl_compat_version = 10;
37 
38 	config.window_width = 700;
39 	config.window_height = 400;
40 	config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
41 	config.khr_no_error_support = PIGLIT_NO_ERRORS;
42 
43 PIGLIT_GL_TEST_CONFIG_END
44 
45 int height = 100, ybase = 0;
46 
47 static const char *prog = "array-texture";
48 
49 static GLboolean have_MESA_texture_array;
50 
51 static GLuint array_tex_1d;
52 static GLuint array_tex_2d;
53 
54 /*
55  * We'll set each texture slice to a different solid color.
56  * XXX a better test would vary the color within each slice too.
57  */
58 #define NUM_COLORS 7
59 
60 static GLfloat colors[NUM_COLORS][3] = {
61    {1.0, 0.0, 0.0},
62    {0.0, 1.0, 0.0},
63    {0.0, 0.0, 1.0},
64    {0.0, 0.0, 1.0},
65    {0.0, 1.0, 0.0},
66    {1.0, 1.0, 0.0},
67    {1.0, 1.0, 1.0}
68 };
69 
70 
71 static const char *frag_shader_2d_array_text =
72    "#extension GL_EXT_texture_array : enable \n"
73    "uniform sampler2DArray tex; \n"
74    "void main() \n"
75    "{ \n"
76    "   gl_FragColor = texture2DArray(tex, gl_TexCoord[0].xyz); \n"
77    "} \n";
78 
79 static GLuint frag_shader_2d_array;
80 static GLuint program_2d_array;
81 
82 
83 static const char *frag_shader_1d_array_text =
84    "#extension GL_EXT_texture_array : enable \n"
85    "uniform sampler1DArray tex; \n"
86    "void main() \n"
87    "{ \n"
88    "   gl_FragColor = texture1DArray(tex, gl_TexCoord[0].xy); \n"
89    "} \n";
90 
91 static GLuint frag_shader_1d_array;
92 static GLuint program_1d_array;
93 
94 
95 
96 /* debug aid */
97 static void
check_error(int line)98 check_error(int line)
99 {
100    GLenum err = glGetError();
101    if (err) {
102       printf("%s: GL error 0x%x at line %d\n", prog, err, line);
103    }
104 }
105 
106 
107 static GLuint
make_2d_array_texture(void)108 make_2d_array_texture(void)
109 {
110    GLfloat img[NUM_COLORS][64][32][4];
111    GLuint tex;
112    int i, j, k;
113 
114    for (i = 0; i < NUM_COLORS; i++) {
115       for (j = 0; j < 64; j++) {
116          for (k = 0; k < 32; k++) {
117             img[i][j][k][0] = colors[i][0];
118             img[i][j][k][1] = colors[i][1];
119             img[i][j][k][2] = colors[i][2];
120             img[i][j][k][3] = 1.0;
121          }
122       }
123    }
124 
125    glGenTextures(1, &tex);
126 
127    glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, tex);
128    check_error(__LINE__);
129 
130    glTexImage3D(GL_TEXTURE_2D_ARRAY_EXT, 0, GL_RGBA,
131                 32, 64, NUM_COLORS, /* w, h, d */
132                 0, /* border */
133                 GL_RGBA, GL_FLOAT, img);
134 
135    glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
136    glTexParameteri(GL_TEXTURE_2D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
137    check_error(__LINE__);
138 
139    return tex;
140 }
141 
142 
143 static GLuint
make_1d_array_texture(void)144 make_1d_array_texture(void)
145 {
146    GLfloat img[NUM_COLORS][16][4];
147    GLuint tex;
148    int i, j;
149 
150    for (i = 0; i < NUM_COLORS; i++) {
151       for (j = 0; j < 16; j++) {
152          img[i][j][0] = colors[i][0];
153          img[i][j][1] = colors[i][1];
154          img[i][j][2] = colors[i][2];
155          img[i][j][3] = 1.0;
156       }
157    }
158 
159    glGenTextures(1, &tex);
160 
161    glBindTexture(GL_TEXTURE_1D_ARRAY_EXT, tex);
162    check_error(__LINE__);
163 
164    glTexImage2D(GL_TEXTURE_1D_ARRAY_EXT, 0, GL_RGBA,
165                 16, NUM_COLORS, /* w, depth */
166                 0, /* border */
167                 GL_RGBA, GL_FLOAT, img);
168 
169    glTexParameteri(GL_TEXTURE_1D_ARRAY_EXT, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
170    glTexParameteri(GL_TEXTURE_1D_ARRAY_EXT, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
171    check_error(__LINE__);
172 
173    return tex;
174 }
175 
176 
177 static GLboolean
test_2d_array_texture(GLuint tex)178 test_2d_array_texture(GLuint tex)
179 {
180    GLboolean pass, ret = GL_TRUE;
181    int i;
182    float width = piglit_width / NUM_COLORS;
183    float x = 0.0;
184 
185    glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, tex);
186    /* render each image in the array, check its color */
187    for (i = 0; i < NUM_COLORS; i++) {
188       GLfloat r = (GLfloat) i;
189 
190       glBegin(GL_POLYGON);
191       glTexCoord3f(0, 0, r);  glVertex2f(x, ybase);
192       glTexCoord3f(1, 0, r);  glVertex2f(x + width, ybase);
193       glTexCoord3f(1, 1, r);  glVertex2f(x + width, ybase + height);
194       glTexCoord3f(0, 1, r);  glVertex2f(x, ybase + height);
195       glEnd();
196 
197       pass = piglit_probe_pixel_rgb(x + (width / 2), ybase + (height / 2),
198 				                       colors[i]);
199 
200       x += width;
201       if (!pass) {
202          printf("%s: failed for 2D image/slice %d\n", prog, i);
203       }
204 
205       ret &= pass;
206    }
207 
208    glBindTexture(GL_TEXTURE_2D_ARRAY_EXT, 0);
209 
210    return ret;
211 }
212 
213 
214 static GLboolean
test_1d_array_texture(GLuint tex)215 test_1d_array_texture(GLuint tex)
216 {
217    GLboolean pass, ret = GL_TRUE;
218    int i;
219    float width = piglit_width / NUM_COLORS;
220    float x = 0.0;
221 
222    glBindTexture(GL_TEXTURE_1D_ARRAY_EXT, tex);
223 
224    /* render each image in the array, check its color */
225    for (i = 0; i < NUM_COLORS; i++) {
226       GLfloat r = (GLfloat) i;
227 
228       glBegin(GL_POLYGON);
229       glTexCoord2f(0, r);  glVertex2f(x, ybase);
230       glTexCoord2f(1, r);  glVertex2f(x + width, ybase);
231       glTexCoord2f(1, r);  glVertex2f(x + width, ybase + height);
232       glTexCoord2f(0, r);  glVertex2f(x, ybase + height);
233       glEnd();
234 
235       glFinish();
236 
237       pass = piglit_probe_pixel_rgb(x + (width / 2), ybase + (height / 2),
238 				    colors[i]);
239 
240       x += width;
241 
242       if (!pass) {
243          printf("%s: failed for 1D image/slice %d\n", prog, i);
244       }
245 
246       ret &= pass;
247    }
248 
249    glBindTexture(GL_TEXTURE_1D_ARRAY_EXT, 0);
250 
251    return ret;
252 }
253 
254 
255 enum piglit_result
piglit_display(void)256 piglit_display(void)
257 {
258    GLboolean pass = GL_TRUE;
259    GLint loc;
260 
261    if (!frag_shader_2d_array) {
262       printf("%s: failed to compile 2D fragment shader.\n", prog);
263       return PIGLIT_FAIL;
264    }
265 
266    if (!program_2d_array) {
267       printf("%s: failed to link 2D shader program.\n", prog);
268       return PIGLIT_FAIL;
269    }
270 
271    if (!frag_shader_1d_array) {
272       printf("%s: failed to compile 1D fragment shader.\n", prog);
273       return PIGLIT_FAIL;
274    }
275 
276    if (!program_1d_array) {
277       printf("%s: failed to link 1D shader program.\n", prog);
278       return PIGLIT_FAIL;
279    }
280 
281 
282    piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
283 
284    ybase = 0;
285    /*
286     * Test 2d array texture with fragment shader
287     */
288    {
289       glClear(GL_COLOR_BUFFER_BIT);
290       glUseProgram(program_2d_array);
291       loc = glGetUniformLocation(program_2d_array, "tex");
292       glUniform1i(loc, 0); /* texture unit p */
293       pass &= test_2d_array_texture(array_tex_2d);
294       glUseProgram(0);
295    }
296 
297    ybase = 100;
298    /*
299     * Test 2d array texture with fixed function
300     */
301    if (have_MESA_texture_array) {
302       glEnable(GL_TEXTURE_2D_ARRAY_EXT);
303       check_error(__LINE__);
304       pass &= test_2d_array_texture(array_tex_2d);
305       glDisable(GL_TEXTURE_2D_ARRAY_EXT);
306       check_error(__LINE__);
307    }
308 
309    ybase = 200;
310    /*
311     * Test 1d array texture with fragment shader
312     */
313    {
314       glUseProgram(program_1d_array);
315       loc = glGetUniformLocation(program_1d_array, "tex");
316       glUniform1i(loc, 0); /* texture unit p */
317       pass &= test_1d_array_texture(array_tex_1d);
318       glUseProgram(0);
319    }
320 
321    ybase = 300;
322    /*
323     * Test 1d array texture with fixed function
324     */
325    if (have_MESA_texture_array) {
326       glEnable(GL_TEXTURE_1D_ARRAY_EXT);
327       check_error(__LINE__);
328       pass &= test_1d_array_texture(array_tex_1d);
329       glDisable(GL_TEXTURE_1D_ARRAY_EXT);
330       check_error(__LINE__);
331    }
332 
333    piglit_present_results();
334    return pass ? PIGLIT_PASS : PIGLIT_FAIL;
335 }
336 
337 
338 void
piglit_init(int argc,char ** argv)339 piglit_init(int argc, char **argv)
340 {
341    piglit_require_extension("GL_EXT_texture_array");
342 
343    have_MESA_texture_array = piglit_is_extension_supported("GL_MESA_texture_array");
344 
345    /* Make shader programs */
346    frag_shader_2d_array =
347       piglit_compile_shader_text(GL_FRAGMENT_SHADER,
348                                  frag_shader_2d_array_text);
349    check_error(__LINE__);
350 
351    program_2d_array = piglit_link_simple_program(0, frag_shader_2d_array);
352    check_error(__LINE__);
353 
354    frag_shader_1d_array =
355       piglit_compile_shader_text(GL_FRAGMENT_SHADER,
356                                  frag_shader_1d_array_text);
357    check_error(__LINE__);
358 
359    program_1d_array = piglit_link_simple_program(0, frag_shader_1d_array);
360    check_error(__LINE__);
361 
362    /* make array textures */
363    array_tex_2d = make_2d_array_texture();
364    array_tex_1d = make_1d_array_texture();
365 }
366