2 * Copyright © 2014 Advanced Micro Devices, Inc.
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 * Marek Olšák <maraeo@gmail.com>
27 #include "piglit-util-gl.h"
30 #define TEX_HALF (TEX_SIZE / 2)
35 PIGLIT_GL_TEST_CONFIG_BEGIN
37 config
.supports_gl_compat_version
= 20;
39 config
.window_width
= 680;
40 config
.window_height
= 620;
41 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
42 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
44 PIGLIT_GL_TEST_CONFIG_END
46 static const char *fs_cube
=
47 "uniform samplerCube tex; \n"
50 " gl_FragColor = textureCube(tex, gl_TexCoord[0].xyz); \n"
53 static const char *fs_cube_array
=
55 "#extension GL_ARB_texture_cube_map_array : enable\n"
56 "uniform samplerCubeArray tex; \n"
59 " gl_FragColor = texture(tex, gl_TexCoord[0]); \n"
62 static GLboolean test_array
;
64 static GLenum num_layers
;
68 static float colors
[][4] = {
77 #define NUM_COLORS ARRAY_SIZE(colors)
82 float *p
= malloc(TEX_SIZE
* TEX_SIZE
* num_layers
* 4 * sizeof(float));
85 for (z
= 0; z
< num_layers
; z
++) {
86 for (y
= 0; y
< TEX_SIZE
; y
++) {
87 for (x
= 0; x
< TEX_SIZE
; x
++) {
88 int quadrant
= y
< TEX_SIZE
/2 ? (x
< TEX_SIZE
/2 ? 0 : 1) :
89 (x
< TEX_SIZE
/2 ? 2 : 3);
90 float *dest
= &p
[(z
*TEX_SIZE
*TEX_SIZE
+ y
*TEX_SIZE
+ x
)*4];
92 memcpy(dest
, colors
[(z
+ quadrant
*2) % NUM_COLORS
],
99 glTexSubImage3D(GL_TEXTURE_CUBE_MAP_ARRAY
, 0, 0, 0, 0,
100 TEX_SIZE
, TEX_SIZE
, num_layers
, GL_RGBA
, GL_FLOAT
, p
);
105 for (i
= 0; i
< 6; i
++) {
106 glTexSubImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ i
, 0, 0, 0,
107 TEX_SIZE
, TEX_SIZE
, GL_RGBA
, GL_FLOAT
,
108 p
+ i
*TEX_SIZE
*TEX_SIZE
*4);
121 glGenTextures(1, &tex
);
122 glBindTexture(target
, tex
);
123 glTexParameteri(target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST_MIPMAP_NEAREST
);
124 glTexParameteri(target
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
126 glTexStorage3D(target
, TEX_LEVELS
, format
,
127 TEX_SIZE
, TEX_SIZE
, num_layers
);
129 glTexStorage2D(target
, TEX_LEVELS
, format
,
132 glGenFramebuffers(1, &fb
);
133 glBindFramebuffer(GL_FRAMEBUFFER
, fb
);
135 for (layer
= 0; layer
< num_layers
; layer
++) {
137 glFramebufferTextureLayer(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
140 glFramebufferTexture2D(GL_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
141 GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ layer
,
144 status
= glCheckFramebufferStatus(GL_FRAMEBUFFER
);
145 if (status
!= GL_FRAMEBUFFER_COMPLETE
) {
150 glViewport(0, 0, TEX_SIZE
, TEX_SIZE
);
151 piglit_ortho_projection(TEX_SIZE
, TEX_SIZE
, GL_FALSE
);
153 glColor4fv(colors
[(layer
+ 0) % NUM_COLORS
]);
154 piglit_draw_rect(0, 0, TEX_HALF
, TEX_HALF
);
156 glColor4fv(colors
[(layer
+ 2) % NUM_COLORS
]);
157 piglit_draw_rect(TEX_HALF
, 0, TEX_HALF
, TEX_HALF
);
159 glColor4fv(colors
[(layer
+ 4) % NUM_COLORS
]);
160 piglit_draw_rect(0, TEX_HALF
, TEX_HALF
, TEX_HALF
);
162 glColor4fv(colors
[(layer
+ 6) % NUM_COLORS
]);
163 piglit_draw_rect(TEX_HALF
, TEX_HALF
, TEX_HALF
, TEX_HALF
);
167 glGenerateMipmap(target
);
168 glDeleteFramebuffers(1, &fb
);
172 #define FACE(x) (GL_TEXTURE_CUBE_MAP_##x - GL_TEXTURE_CUBE_MAP_POSITIVE_X)
175 piglit_draw_rect_face(float x
, float y
, float w
, float h
, int face
, int cube_layer
)
179 float sign
= face
% 2 ? -1 : 1;
199 case FACE(POSITIVE_X
):
200 case FACE(NEGATIVE_X
):
206 tex
[3][1] = -1 * sign
;
209 tex
[0][1] = -1 * sign
;
212 tex
[1][1] = 1 * sign
;
215 tex
[2][1] = 1 * sign
;
219 case FACE(POSITIVE_Y
):
220 case FACE(NEGATIVE_Y
):
226 tex
[0][0] = 1 * sign
;
229 tex
[1][0] = -1 * sign
;
232 tex
[2][0] = -1 * sign
;
235 tex
[3][0] = 1 * sign
;
239 case FACE(POSITIVE_Z
):
240 case FACE(NEGATIVE_Z
):
247 tex
[0][1] = 1 * sign
;
250 tex
[1][1] = 1 * sign
;
253 tex
[2][1] = -1 * sign
;
256 tex
[3][1] = -1 * sign
;
263 tex
[0][3] = cube_layer
;
264 tex
[1][3] = cube_layer
;
265 tex
[2][3] = cube_layer
;
266 tex
[3][3] = cube_layer
;
268 glVertexPointer(4, GL_FLOAT
, 0, verts
);
269 glTexCoordPointer(4, GL_FLOAT
, 0, tex
);
270 glEnableClientState(GL_VERTEX_ARRAY
);
271 glEnableClientState(GL_TEXTURE_COORD_ARRAY
);
273 glDrawArrays(GL_QUADS
, 0, 4);
275 glDisableClientState(GL_VERTEX_ARRAY
);
276 glDisableClientState(GL_TEXTURE_COORD_ARRAY
);
280 draw_face(int face
, int cube_layer
, int x
, int y
)
285 loc
= glGetUniformLocation(prog
, "tex");
286 glUniform1i(loc
, 0); /* texture unit p */
288 glViewport(0, 0, piglit_width
, piglit_height
);
289 piglit_ortho_projection(piglit_width
, piglit_height
, GL_FALSE
);
291 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
293 piglit_draw_rect_face(x
, y
, DRAW_SIZE
, DRAW_SIZE
, face
, cube_layer
);
298 draw_cube(int x
, int y
, int level
, int cube_layer
)
300 glTexParameteri(target
, GL_TEXTURE_MIN_LOD
, level
);
301 glTexParameteri(target
, GL_TEXTURE_MAX_LOD
, level
);
303 draw_face(FACE(POSITIVE_X
), cube_layer
, x
, y
+DRAW_SIZE
);
304 draw_face(FACE(POSITIVE_Y
), cube_layer
, x
+DRAW_SIZE
, y
+DRAW_SIZE
);
305 draw_face(FACE(NEGATIVE_X
), cube_layer
, x
+DRAW_SIZE
*2, y
+DRAW_SIZE
);
306 draw_face(FACE(NEGATIVE_Y
), cube_layer
, x
+DRAW_SIZE
*3, y
+DRAW_SIZE
);
307 draw_face(FACE(POSITIVE_Z
), cube_layer
, x
+DRAW_SIZE
, y
+DRAW_SIZE
*2);
308 draw_face(FACE(NEGATIVE_Z
), cube_layer
, x
+DRAW_SIZE
, y
);
312 draw_mipmap_tree(int x
, int y
)
316 for (i
= 0; i
< TEX_LEVELS
; i
++) {
317 int cubes
= num_layers
/ 6;
319 for (j
= 0; j
< cubes
; j
++) {
320 draw_cube(x
+ j
*(DRAW_SIZE
* 4 + 5),
321 y
+ i
*(DRAW_SIZE
* 3 + 5), i
, j
);
327 test_face(int face
, int level
, int cube
, float *observed
)
329 int size
= TEX_SIZE
>> level
;
330 int layer
= cube
*6 + face
;
335 e
= malloc(size
* size
* 4 * sizeof(float));
338 memset(e
, 0, 4 * sizeof(float));
340 for (i
= 0; i
< 4; i
++)
341 for (c
= 0; c
< 4; c
++)
342 e
[c
] += colors
[(layer
+ i
*2) % NUM_COLORS
][c
] * 0.25;
345 for (y
= 0; y
< size
; y
++) {
346 for (x
= 0; x
< size
; x
++) {
347 int quadrant
= y
< size
/2 ? (x
< size
/2 ? 0 : 1) :
348 (x
< size
/2 ? 2 : 3);
349 float *color
= colors
[(layer
+ quadrant
*2) % NUM_COLORS
];
351 memcpy(&e
[(y
*size
+x
)*4], color
, sizeof(float) * 4);
357 for (y
= 0; y
< size
; y
++) {
358 for (x
= 0; x
< size
; x
++) {
359 float *probe
= &observed
[(y
*size
+x
)*4];
360 float *expected
= &e
[(y
*size
+x
)*4];
362 for (i
= 0; i
< 4; ++i
) {
363 if (fabs(probe
[i
] - expected
[i
]) >= piglit_tolerance
[i
]) {
364 printf("Probe color at (%i,%i)\n", x
, y
);
365 printf(" Expected: %f %f %f %f\n",
366 expected
[0], expected
[1], expected
[2], expected
[3]);
367 printf(" Observed: %f %f %f %f\n",
368 probe
[0], probe
[1], probe
[2], probe
[3]);
369 printf(" when testing face %i, level %i, cube %i\n",
384 test_mipmap_tree(void)
389 for (level
= 0; level
< TEX_LEVELS
; level
++) {
390 int size
= TEX_SIZE
>> level
;
393 /* With a compressed texture, skip checking the second and
394 * third last levels, because one DXTC block cannot contain
395 * more than 2 colors.
397 * However, always test the last level, which should only
398 * contain one color, which is the average of all 4.
400 if (format
== GL_COMPRESSED_RGB_S3TC_DXT1_EXT
&&
401 level
>= TEX_LEVELS
-3 && level
<= TEX_LEVELS
-2)
405 observed
= malloc(num_layers
* size
* size
* 4 * sizeof(float));
406 glGetTexImage(target
, level
, GL_RGBA
, GL_FLOAT
, observed
);
408 for (layer
= 0; layer
< num_layers
; layer
++) {
409 pass
= pass
&& test_face(layer
% 6, level
, layer
/ 6,
410 observed
+ layer
* size
* size
* 4);
416 for (layer
= 0; layer
< num_layers
; layer
++) {
417 observed
= malloc(size
* size
* 4 * sizeof(float));
418 glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ layer
,
419 level
, GL_RGBA
, GL_FLOAT
, observed
);
421 pass
= pass
&& test_face(layer
, level
, 0, observed
);
434 GLboolean pass
= GL_TRUE
;
437 glClear(GL_COLOR_BUFFER_BIT
);
439 tex
= create_texcube();
441 draw_mipmap_tree(5, 5);
443 pass
= test_mipmap_tree();
445 glDeleteTextures(1, &tex
);
446 piglit_present_results();
447 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
450 void piglit_init(int argc
, char **argv
)
454 piglit_require_extension("GL_ARB_framebuffer_object");
455 piglit_require_extension("GL_ARB_texture_storage");
456 piglit_require_GLSL_version(120);
459 target
= GL_TEXTURE_CUBE_MAP
;
462 for (i
= 1; i
< argc
; i
++) {
463 if (strcmp(argv
[i
], "array") == 0) {
464 piglit_require_GLSL_version(130);
465 piglit_require_extension("GL_ARB_texture_cube_map_array");
466 test_array
= GL_TRUE
;
467 target
= GL_TEXTURE_CUBE_MAP_ARRAY
;
470 else if (strcmp(argv
[i
], "RGB9_E5") == 0) {
471 /* Test a non-renderable format. */
472 piglit_require_extension("GL_EXT_texture_shared_exponent");
475 else if (strcmp(argv
[i
], "S3TC_DXT1") == 0) {
476 /* Test a compressed format. */
477 piglit_require_extension("GL_EXT_texture_compression_s3tc");
478 format
= GL_COMPRESSED_RGB_S3TC_DXT1_EXT
;
479 piglit_set_tolerance_for_bits(5, 6, 5, 8);
486 prog
= piglit_build_simple_program(NULL
, test_array
? fs_cube_array
:
489 glClearColor(0.25, 0.25, 0.25, 0.25);