conversion-explicit: use a different value for normalized +/- min
[piglit.git] / tests / spec / arb_copy_image / levels-copy.c
blob9df1461c831ac61e1a425bb523b518dba7117807
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
12 * Software.
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
20 * IN THE SOFTWARE.
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"
32 #include <math.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
43 enum piglit_result
44 piglit_display(void)
46 return PIGLIT_FAIL;
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;
56 struct image {
57 GLuint texture;
58 GLenum target;
59 int levels;
60 int width, height, depth;
63 static void
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) {
72 case GL_TEXTURE_1D:
73 case GL_TEXTURE_1D_ARRAY:
74 *height = 1;
75 *depth = 1;
76 break;
78 case GL_TEXTURE_CUBE_MAP:
79 *depth = 6;
80 break;
82 case GL_TEXTURE_2D:
83 case GL_TEXTURE_2D_ARRAY:
84 *depth = 1;
85 break;
89 static void
90 init_image(struct image *img, GLenum texture_type,
91 int width, int height, int depth, int levels)
93 img->target = texture_type;
95 img->width = width;
96 img->height = height;
97 img->depth = depth;
98 img->levels = levels;
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);
108 static void
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);
116 GLuint *data = NULL;
117 if (upload_data) {
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) {
125 case GL_TEXTURE_1D:
126 glTexImage1D(img->target, level,
127 GL_RGBA8, width, 0,
128 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, data);
129 break;
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,
136 data);
138 break;
140 case GL_TEXTURE_2D:
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);
145 break;
147 case GL_TEXTURE_3D:
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);
152 break;
153 default:
154 assert(!"Invalid target");
157 free(data);
160 static bool
161 check_image(GLenum target_type, int level, int data_size)
163 bool pass = true;
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) {
173 pass = false;
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);
178 break;
183 free(data);
185 return pass;
188 enum tex_init_order {
189 TEX_ORDER_FORWARD,
190 TEX_ORDER_BACKWARD,
192 TEX_ORDER_END,
195 static bool
196 run_test(GLenum target_type, enum tex_init_order init_order)
198 struct image srcImg, dstImg;
199 bool pass = true;
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);
211 } else {
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;
237 } else {
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'");
251 return pass;
254 void
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;
262 break;
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.
272 bool pass = true;
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);