2 * Copyright © 2008-2009 Intel Corporation
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 * Eric Anholt <eric@anholt.net>
28 #include "piglit-util.h"
33 #define WIN_WIDTH ((MAX_SIZE * 6 + PAD * 9) * 2)
34 #define WIN_HEIGHT 400
36 int piglit_window_mode
= GLUT_DOUBLE
| GLUT_RGB
;
37 int piglit_width
= WIN_WIDTH
;
38 int piglit_height
= WIN_HEIGHT
;
40 static GLfloat colors
[][3] = {
52 * Find the first bit set in i and return the index set of that bit.
63 for (bit
= 1; !(i
& 1); bit
++) {
72 set_face_image(int level
, GLenum face
, int size
, int color
)
74 GLfloat
*color1
= colors
[color
];
75 GLfloat
*color2
= colors
[(color
+ 1) % ARRAY_SIZE(colors
)];
79 tex
= malloc(size
* size
* 3 * sizeof(GLfloat
));
81 /* Set the texture for this face to one corner being color2 and the
82 * rest color1. If the texture is 1x1, then it's all color1.
84 for (y
= 0; y
< size
; y
++) {
85 for (x
= 0; x
< size
; x
++) {
86 GLfloat
*chosen_color
;
88 if (y
>= (size
/ 2) || x
>= (size
/ 2))
89 chosen_color
= color1
;
91 chosen_color
= color2
;
93 tex
[(y
* size
+ x
) * 3 + 0] = chosen_color
[0];
94 tex
[(y
* size
+ x
) * 3 + 1] = chosen_color
[1];
95 tex
[(y
* size
+ x
) * 3 + 2] = chosen_color
[2];
99 glTexImage2D(face
, level
, GL_RGB
, size
, size
, 0, GL_RGB
, GL_FLOAT
, tex
);
105 * Tests that the mipmap drawn at (x,y)-(x+size,y+size) has the majority color,
106 * with color+1 in bottom left.
109 test_results(int x
, int y
, int size
, int level
, int face
, GLboolean mipmapped
,
112 GLfloat
*color1
= colors
[color
];
113 GLfloat
*color2
= colors
[(color
+ 1) % ARRAY_SIZE(colors
)];
114 GLboolean pass
= GL_TRUE
;
115 int x1
= x
+ size
/ 4, x2
= x
+ size
* 3 / 4;
116 int y1
= y
+ size
/ 4, y2
= y
+ size
* 3 / 4;
119 pass
= pass
&& piglit_probe_pixel_rgb(x1
, y1
, color1
);
121 pass
= pass
&& piglit_probe_pixel_rgb(x1
, y1
, color2
);
122 pass
= pass
&& piglit_probe_pixel_rgb(x2
, y1
, color1
);
123 pass
= pass
&& piglit_probe_pixel_rgb(x2
, y2
, color1
);
124 pass
= pass
&& piglit_probe_pixel_rgb(x1
, y2
, color1
);
128 int base_size
= size
* (1 << level
);
129 printf("Cube map failed at size %dx%d, level %d (%dx%d), face %s%s\n",
130 base_size
, base_size
, level
, size
, size
,
131 cube_face_names
[face
],
132 mipmapped
? ", mipmapped" : "");
139 draw_at_size(int size
, int x_offset
, int y_offset
, GLboolean mipmapped
)
141 GLfloat row_y
= PAD
+ y_offset
;
143 int color
= 0, level
= 0;
145 GLboolean pass
= GL_TRUE
;
147 /* Create the texture. */
148 glGenTextures(1, &texname
);
149 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB
, texname
);
151 /* For each face drawing, we want to only see that face's contents at
155 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB
,
156 GL_TEXTURE_MIN_FILTER
,
157 GL_NEAREST_MIPMAP_NEAREST
);
159 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB
,
160 GL_TEXTURE_MIN_FILTER
,
163 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB
,
164 GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
165 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB
,
166 GL_TEXTURE_WRAP_S
, GL_CLAMP_TO_EDGE
);
167 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB
,
168 GL_TEXTURE_WRAP_T
, GL_CLAMP_TO_EDGE
);
170 /* Fill in faces on each level */
171 for (dim
= size
; dim
> 0; dim
/= 2) {
172 for (face
= 0; face
< 6; face
++) {
173 set_face_image(level
, cube_face_targets
[face
],
175 color
= (color
+ 1) % ARRAY_SIZE(colors
);
183 glEnable(GL_TEXTURE_CUBE_MAP_ARB
);
187 for (dim
= size
; dim
> 0; dim
/= 2) {
188 GLfloat row_x
= PAD
+ x_offset
;
190 for (face
= 0; face
< 6; face
++) {
191 GLfloat base_x
= row_x
+ face
* (MAX_SIZE
+ PAD
);
192 GLfloat base_y
= row_y
;
196 glTexCoord3fv(cube_face_texcoords
[face
][0]);
197 glVertex2f(base_x
, base_y
);
199 glTexCoord3fv(cube_face_texcoords
[face
][1]);
200 glVertex2f(base_x
+ dim
, base_y
);
202 glTexCoord3fv(cube_face_texcoords
[face
][2]);
203 glVertex2f(base_x
+ dim
, base_y
+ dim
);
205 glTexCoord3fv(cube_face_texcoords
[face
][3]);
206 glVertex2f(base_x
, base_y
+ dim
);
211 pass
= test_results(base_x
, base_y
,
217 color
= (color
+ 1) % ARRAY_SIZE(colors
);
227 glDeleteTextures(1, &texname
);
237 GLboolean pass
= GL_TRUE
;
238 int i
= 0, y_offset
= 0;
241 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
243 /* Clear background to gray */
244 glClearColor(0.5, 0.5, 0.5, 1.0);
245 glClear(GL_COLOR_BUFFER_BIT
);
247 /* First, do each size from MAX_SIZExMAX_SIZE to 1x1 as a
248 * single texture level.
251 for (dim
= MAX_SIZE
; dim
> 0; dim
/= 2) {
252 pass
= draw_at_size(dim
, 0, y_offset
, GL_FALSE
) && pass
;
253 y_offset
+= dim
+ PAD
;
256 /* Next, do each size with mipmaps from MAX_SIZExMAX_SIZE
260 for (dim
= MAX_SIZE
; dim
> 0; dim
/= 2) {
261 int x_offset
= (i
% 2 == 1) ? 0 : WIN_WIDTH
/ 2;
263 row_dim
= (row_dim
< dim
) ? dim
: row_dim
;
265 pass
&= draw_at_size(dim
, x_offset
, y_offset
, GL_TRUE
);
267 y_offset
+= row_dim
* 2 + (ffs(dim
) + 3) * PAD
;
275 return pass
? PIGLIT_SUCCESS
: PIGLIT_FAILURE
;
279 piglit_init(int argc
, char **argv
)
281 piglit_require_extension("GL_ARB_texture_cube_map");