1 /* Copyright © 2020 Intel Corporation
3 * Permission is hereby granted, free of charge, to any person obtaining a
4 * copy of this software and associated documentation files (the "Software"),
5 * to deal in the Software without restriction, including without limitation
6 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
7 * and/or sell copies of the Software, and to permit persons to whom the
8 * Software is furnished to do so, subject to the following conditions:
10 * The above copyright notice and this permission notice (including the next
11 * paragraph) shall be included in all copies or substantial portions of the
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
23 /** @file layers-copy.c
25 * Tests that glCopyImageSubData correctly copies all levels of a texture.
26 * Also tests that the order in which levels are initialized doesn't affect
27 * the copying (some drivers, e.g. gallium drivers, may be sensitive to the
28 * initialization order).
31 #include "piglit-util-gl.h"
34 PIGLIT_GL_TEST_CONFIG_BEGIN
36 config
.supports_gl_compat_version
= 13;
38 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
| PIGLIT_GL_VISUAL_DOUBLE
;
39 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
41 PIGLIT_GL_TEST_CONFIG_END
49 static const int tex_default_width
= 32;
50 static const int tex_default_height
= 32;
51 static const int tex_default_depth
= 8;
52 static const int tex_default_levels
= 6;
54 static int illegal_levels_amount
= 0;
60 int width
, height
, depth
;
64 get_img_dims(struct image
*img
, int level
,
65 int *width
, int *height
, int *depth
)
67 *width
= MAX2(img
->width
>> level
, 1);
68 *height
= MAX2(img
->height
>> level
, 1);
69 *depth
= MAX2(img
->depth
>> level
, 1);
71 switch (img
->target
) {
73 case GL_TEXTURE_1D_ARRAY
:
78 case GL_TEXTURE_CUBE_MAP
:
83 case GL_TEXTURE_2D_ARRAY
:
90 init_image(struct image
*img
, GLenum texture_type
,
91 int width
, int height
, int depth
, int levels
)
93 img
->target
= texture_type
;
100 get_img_dims(img
, 0, &img
->width
, &img
->height
, &img
->depth
);
102 glGenTextures(1, &img
->texture
);
103 glBindTexture(img
->target
, img
->texture
);
104 glTexParameteri(img
->target
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
105 glTexParameteri(img
->target
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
109 tex_image(struct image
*img
, int level
, bool upload_data
)
111 glBindTexture(img
->target
, img
->texture
);
113 int width
, height
, depth
;
114 get_img_dims(img
, level
, &width
, &height
, &depth
);
118 data
= malloc(width
* height
* depth
* sizeof(GLuint
));
119 for (int i
= 0; i
< width
* height
* depth
; i
++) {
120 data
[i
] = 0xFF / (level
+ 1);
124 switch (img
->target
) {
126 glTexImage1D(img
->target
, level
,
128 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, data
);
131 case GL_TEXTURE_CUBE_MAP
:
132 for (int k
= 0; k
< 6; ++k
) {
133 glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ k
, level
,
134 GL_RGBA8
, width
, height
, 0,
135 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
,
141 case GL_TEXTURE_1D_ARRAY
:
142 glTexImage2D(img
->target
, level
,
143 GL_RGBA8
, width
, height
, 0,
144 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, data
);
148 case GL_TEXTURE_2D_ARRAY
:
149 glTexImage3D(img
->target
, level
,
150 GL_RGBA8
, width
, height
, depth
, 0,
151 GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, data
);
154 assert(!"Invalid target");
161 check_image(GLenum target_type
, int level
, int data_size
)
164 GLuint expected
= 0xFF / (level
+ 1);
166 GLuint
*data
= malloc(data_size
* sizeof(GLuint
));
167 glGetTexImage(target_type
, level
, GL_RGBA
, GL_UNSIGNED_INT_8_8_8_8
, data
);
169 if(level
< tex_default_levels
) /*Skip illegal levels*/
171 for (int i
= 0; i
< data_size
; i
++) {
172 if (data
[i
] != expected
) {
174 fprintf(stderr
, "%s: level %d, texel idx %d (%d total) "
175 "comparison failed (%d != %d)\n",
176 piglit_get_gl_enum_name(target_type
),
177 level
, i
, data_size
, data
[i
], expected
);
188 enum tex_init_order
{
196 run_test(GLenum target_type
, enum tex_init_order init_order
)
198 struct image srcImg
, dstImg
;
201 init_image(&srcImg
, target_type
, tex_default_width
, tex_default_height
,
202 tex_default_depth
, tex_default_levels
+ illegal_levels_amount
);
203 init_image(&dstImg
, target_type
, tex_default_width
, tex_default_height
,
204 tex_default_depth
, tex_default_levels
+ illegal_levels_amount
);
206 if (init_order
== TEX_ORDER_FORWARD
) {
207 for(int level
= 0; level
< srcImg
.levels
; level
++) {
208 tex_image(&srcImg
, level
, true);
209 tex_image(&dstImg
, level
, false);
212 for(int level
= srcImg
.levels
- 1; level
>= 0; level
--) {
213 tex_image(&srcImg
, level
, true);
214 tex_image(&dstImg
, level
, false);
218 for(int level
= 0; level
< srcImg
.levels
; level
++) {
219 int width
, height
, depth
;
220 get_img_dims(&srcImg
, level
, &width
, &height
, &depth
);
222 glCopyImageSubData(srcImg
.texture
, target_type
, level
, 0, 0, 0, dstImg
.texture
,
223 target_type
, level
, 0, 0, 0, width
, height
, depth
);
226 for(int level
= 0; level
< srcImg
.levels
; level
++) {
227 int width
, height
, depth
;
228 get_img_dims(&srcImg
, level
, &width
, &height
, &depth
);
230 glBindTexture(target_type
, dstImg
.texture
);
232 if (target_type
== GL_TEXTURE_CUBE_MAP
) {
233 for (int k
= 0; k
< 6; ++k
) {
234 pass
= check_image(GL_TEXTURE_CUBE_MAP_POSITIVE_X
+ k
,
235 level
, width
* height
) && pass
;
238 pass
= check_image(target_type
, level
, width
* height
* depth
) && pass
;
242 glDeleteTextures(1, &srcImg
.texture
);
243 glDeleteTextures(1, &dstImg
.texture
);
245 piglit_report_subtest_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
,
246 "Target type: %s, width: %d, height: %d, depth: %d, levels: %d, init order: %s",
247 piglit_get_gl_enum_name(target_type
), srcImg
.width
, srcImg
.height
,
248 srcImg
.depth
, srcImg
.levels
,
249 init_order
== TEX_ORDER_FORWARD
? "'forward'" : "'backward'");
255 piglit_init(int argc
, char **argv
)
257 piglit_require_extension("GL_ARB_copy_image");
259 for (int i
= 1; i
< argc
; i
++) {
260 if (strcmp(argv
[i
], "add-illegal-levels") == 0) {
261 illegal_levels_amount
= 2;
265 /* When ran with 'add-illegal-levels' argument,
266 * we generate 2 more mipmap levels than allowed by texture size.
267 * Which can possibly corrupt data of existing layers.
268 * We don't check the data correctness of illegal levels, since
269 * spec doesn't say what should be in them.
274 for (enum tex_init_order order
= TEX_ORDER_FORWARD
; order
< TEX_ORDER_END
; order
++) {
275 pass
= run_test(GL_TEXTURE_1D
, order
) && pass
;
276 pass
= run_test(GL_TEXTURE_2D
, order
) && pass
;
277 pass
= run_test(GL_TEXTURE_3D
, order
) && pass
;
279 if (piglit_is_extension_supported("GL_EXT_texture_array")) {
280 pass
= run_test(GL_TEXTURE_1D_ARRAY
, order
) && pass
;
281 pass
= run_test(GL_TEXTURE_2D_ARRAY
, order
) && pass
;
284 if (piglit_is_extension_supported("GL_ARB_texture_cube_map")) {
285 pass
= run_test(GL_TEXTURE_CUBE_MAP
, order
) && pass
;
289 piglit_report_result(pass
? PIGLIT_PASS
: PIGLIT_FAIL
);