add pbobench: a benchmark for pbo functions
[piglit.git] / tests / texturing / cubemap.c
blob8fea1cd5b501f2cf69463f78a506432aa145c335
1 /*
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
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 * Eric Anholt <eric@anholt.net>
28 #include "piglit-util-gl.h"
30 #define PAD 5
32 PIGLIT_GL_TEST_CONFIG_BEGIN
34 config.supports_gl_compat_version = 10;
36 config.window_width = (64*6+PAD*9)*2;
37 config.window_height = 400;
38 config.window_visual = PIGLIT_GL_VISUAL_DOUBLE | PIGLIT_GL_VISUAL_RGB;
39 config.khr_no_error_support = PIGLIT_NO_ERRORS;
41 PIGLIT_GL_TEST_CONFIG_END
43 static bool use_pbo;
44 static int max_size;
46 static GLfloat colors[][3] = {
47 {1.0, 1.0, 1.0},
48 {1.0, 1.0, 0.0},
49 {1.0, 0.0, 0.0},
50 {1.0, 0.0, 1.0},
51 {0.0, 0.0, 1.0},
52 {0.0, 1.0, 1.0},
53 {0.0, 1.0, 0.0},
56 static void
57 set_face_image(GLenum internalformat, int level, GLenum face, int size, int color)
59 GLfloat *color1 = colors[color];
60 GLfloat *color2 = colors[(color + 1) % ARRAY_SIZE(colors)];
61 GLfloat *tex;
62 GLuint buffer;
63 int x, y;
65 tex = malloc(size * size * 3 * sizeof(GLfloat));
67 /* Set the texture for this face to one corner being color2 and the
68 * rest color1. If the texture is 1x1, then it's all color1.
70 for (y = 0; y < size; y++) {
71 for (x = 0; x < size; x++) {
72 GLfloat *chosen_color;
74 if (y >= (size / 2) || x >= (size / 2))
75 chosen_color = color1;
76 else
77 chosen_color = color2;
79 tex[(y * size + x) * 3 + 0] = chosen_color[0];
80 tex[(y * size + x) * 3 + 1] = chosen_color[1];
81 tex[(y * size + x) * 3 + 2] = chosen_color[2];
85 if (use_pbo) {
86 glGenBuffers(1, &buffer);
87 glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
88 glBufferData(GL_PIXEL_UNPACK_BUFFER, size * size * 3 * sizeof(GLfloat),
89 tex, GL_STREAM_DRAW);
92 glTexImage2D(face, level, internalformat, size, size, 0, GL_RGB, GL_FLOAT,
93 use_pbo ? NULL : tex);
95 if (use_pbo)
96 glDeleteBuffers(1, &buffer);
98 free(tex);
102 * Tests that the mipmap drawn at (x,y)-(x+size,y+size) has the majority color,
103 * with color+1 in bottom left.
105 static GLboolean
106 test_results(int x, int y, int size, int level, int face, GLboolean mipmapped,
107 int color)
109 GLfloat *color1 = colors[color];
110 GLfloat *color2 = colors[(color + 1) % ARRAY_SIZE(colors)];
111 GLboolean pass = GL_TRUE;
112 int x1 = x + size / 4, x2 = x + size * 3 / 4;
113 int y1 = y + size / 4, y2 = y + size * 3 / 4;
115 if (size == 1) {
116 pass = pass && piglit_probe_pixel_rgb(x1, y1, color1);
117 } else {
118 pass = pass && piglit_probe_pixel_rgb(x1, y1, color2);
119 pass = pass && piglit_probe_pixel_rgb(x2, y1, color1);
120 pass = pass && piglit_probe_pixel_rgb(x2, y2, color1);
121 pass = pass && piglit_probe_pixel_rgb(x1, y2, color1);
124 if (!pass) {
125 int base_size = size * (1 << level);
126 printf("Cube map failed at size %dx%d, level %d (%dx%d), face %s%s\n",
127 base_size, base_size, level, size, size,
128 cube_face_names[face],
129 mipmapped ? ", mipmapped" : "");
132 return pass;
135 static GLboolean
136 draw_at_size(GLenum internalformat, int size, int x_offset, int y_offset, GLboolean mipmapped)
138 GLfloat row_y = PAD + y_offset;
139 int dim, face;
140 int color = 0, level = 0;
141 GLuint texname;
142 GLboolean pass = GL_TRUE;
144 /* Create the texture. */
145 glGenTextures(1, &texname);
146 glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, texname);
148 /* For each face drawing, we want to only see that face's contents at
149 * that mipmap level.
151 if (mipmapped) {
152 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,
153 GL_TEXTURE_MIN_FILTER,
154 GL_NEAREST_MIPMAP_NEAREST);
155 } else {
156 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,
157 GL_TEXTURE_MIN_FILTER,
158 GL_NEAREST);
160 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,
161 GL_TEXTURE_MAG_FILTER, GL_NEAREST);
162 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,
163 GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
164 glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB,
165 GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
167 /* Fill in faces on each level */
168 for (dim = size; dim > 0; dim /= 2) {
169 for (face = 0; face < 6; face++) {
170 set_face_image(internalformat, level, cube_face_targets[face],
171 dim, color);
172 color = (color + 1) % ARRAY_SIZE(colors);
174 if (!mipmapped)
175 break;
177 level++;
180 glEnable(GL_TEXTURE_CUBE_MAP_ARB);
182 color = 0;
183 level = 0;
184 for (dim = size; dim > 0; dim /= 2) {
185 GLfloat row_x = PAD + x_offset;
187 for (face = 0; face < 6; face++) {
188 GLfloat base_x = row_x + face * (max_size + PAD);
189 GLfloat base_y = row_y;
191 glBegin(GL_QUADS);
193 glTexCoord3fv(cube_face_texcoords[face][0]);
194 glVertex2f(base_x, base_y);
196 glTexCoord3fv(cube_face_texcoords[face][1]);
197 glVertex2f(base_x + dim, base_y);
199 glTexCoord3fv(cube_face_texcoords[face][2]);
200 glVertex2f(base_x + dim, base_y + dim);
202 glTexCoord3fv(cube_face_texcoords[face][3]);
203 glVertex2f(base_x, base_y + dim);
205 glEnd();
207 if (dim > 2) {
208 pass = test_results(base_x, base_y,
209 dim, level, face,
210 mipmapped,
211 color) && pass;
214 color = (color + 1) % ARRAY_SIZE(colors);
217 if (!mipmapped)
218 break;
220 row_y += dim + PAD;
221 level++;
224 glDeleteTextures(1, &texname);
226 return pass;
229 static bool
230 test_format(GLenum internalformat)
232 bool pass = true;
233 int dim;
234 int i = 0, y_offset = 0;
235 int row_dim = 0;
237 /* Clear background to gray */
238 glClearColor(0.5, 0.5, 0.5, 1.0);
239 glClear(GL_COLOR_BUFFER_BIT);
241 /* First, do each size from MAX_SIZExMAX_SIZE to 1x1 as a
242 * single texture level.
244 y_offset = 0;
245 for (dim = max_size; dim > 0; dim /= 2) {
246 pass = draw_at_size(internalformat, dim, 0, y_offset, GL_FALSE) && pass;
247 y_offset += dim + PAD;
250 /* Next, do each size with mipmaps from MAX_SIZExMAX_SIZE
251 * to 1x1.
253 y_offset = 0;
254 for (dim = max_size; dim > 0; dim /= 2) {
255 int x_offset = (i % 2 == 1) ? 0 : piglit_width / 2;
257 row_dim = (row_dim < dim) ? dim : row_dim;
259 pass &= draw_at_size(internalformat, dim, x_offset, y_offset, GL_TRUE);
260 if (i % 2 == 0) {
261 y_offset += row_dim * 2 + (ffs(dim) + 3) * PAD;
262 row_dim = 0;
264 i++;
267 return pass;
270 enum piglit_result
271 piglit_display(void)
273 static const GLenum internalformats[] = {
274 GL_RGB,
275 GL_RGBA,
277 GLboolean pass = GL_TRUE;
278 unsigned i;
280 piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
282 for (i = 0; i < ARRAY_SIZE(internalformats); ++i)
283 pass = test_format(internalformats[i]) && pass;
285 piglit_present_results();
287 return pass ? PIGLIT_PASS : PIGLIT_FAIL;
290 void
291 piglit_init(int argc, char **argv)
293 int i;
295 piglit_require_extension("GL_ARB_texture_cube_map");
297 max_size = 64;
299 for (i = 1; i < argc; i++) {
300 if (strcmp(argv[i], "npot") == 0) {
301 piglit_require_extension("GL_ARB_texture_non_power_of_two");
302 max_size = 50;
303 } else if (strcmp(argv[i], "pbo") == 0) {
304 piglit_require_extension("GL_ARB_pixel_buffer_object");
305 use_pbo = true;