2 * Copyright 2014 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
25 * This tests glCopySubImageData on different multisampled texture
26 * formats. One texture is created and filled with random data. The
27 * texture is then copied to a second texture, the texture is downloaded,
28 * and the data verified. Because glCopySubImageData is supposed to be a
29 * direct memcpy, the copy is verified to be bit-for-bit copy of the
33 #include "piglit-util-gl.h"
36 #define DEFAULT_SRC_LEVEL 1
37 #define DEFAULT_DST_LEVEL 3
39 PIGLIT_GL_TEST_CONFIG_BEGIN
41 config
.supports_gl_compat_version
= 13;
43 config
.window_visual
= PIGLIT_GL_VISUAL_RGB
| PIGLIT_GL_VISUAL_DOUBLE
;
44 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
46 PIGLIT_GL_TEST_CONFIG_END
48 struct texture_format
{
49 GLenum internal_format
;
52 bool can_be_reinterpreted
;
58 static const struct texture_format formats
[] = {
59 { GL_RED
, GL_RED
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
60 { GL_R8UI
, GL_RED_INTEGER
, GL_UNSIGNED_BYTE
, true, 1, 1, 1 },
61 { GL_R8I
, GL_RED_INTEGER
, GL_BYTE
, true, 1, 1, 1 },
62 { GL_R8
, GL_RED
, GL_UNSIGNED_BYTE
, true, 1, 1, 1 },
63 { GL_R8_SNORM
, GL_RED
, GL_BYTE
, true, 1, 1, 1 },
65 { GL_RG
, GL_RG
, GL_UNSIGNED_BYTE
, false, 2, 1, 1 },
66 { GL_RG8UI
, GL_RG_INTEGER
, GL_UNSIGNED_BYTE
, true, 2, 1, 1 },
67 { GL_RG8I
, GL_RG_INTEGER
, GL_BYTE
, true, 2, 1, 1 },
68 { GL_RG8
, GL_RG
, GL_UNSIGNED_BYTE
, true, 2, 1, 1 },
69 { GL_RG8_SNORM
, GL_RG
, GL_BYTE
, true, 2, 1, 1 },
70 { GL_R16UI
, GL_RED_INTEGER
, GL_UNSIGNED_SHORT
, true, 2, 1, 1 },
71 { GL_R16I
, GL_RED_INTEGER
, GL_SHORT
, true, 2, 1, 1 },
72 { GL_R16
, GL_RED
, GL_UNSIGNED_SHORT
, true, 2, 1, 1 },
73 { GL_R16_SNORM
, GL_RED
, GL_SHORT
, true, 2, 1, 1 },
75 { GL_RGB
, GL_RGB
, GL_UNSIGNED_BYTE
, false, 3, 1, 1 },
76 { GL_RGB8UI
, GL_RGB_INTEGER
, GL_UNSIGNED_BYTE
, true, 3, 1, 1 },
77 { GL_RGB8I
, GL_RGB_INTEGER
, GL_BYTE
, true, 3, 1, 1 },
78 { GL_RGB8
, GL_RGB
, GL_UNSIGNED_BYTE
, true, 3, 1, 1 },
79 { GL_RGB8_SNORM
, GL_RGB
, GL_BYTE
, true, 3, 1, 1 },
81 { GL_RGBA
, GL_RGBA
, GL_UNSIGNED_BYTE
, false, 4, 1, 1 },
82 { GL_RGBA8UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_BYTE
, true, 4, 1, 1 },
83 { GL_RGBA8I
, GL_RGBA_INTEGER
, GL_BYTE
, true, 4, 1, 1 },
84 { GL_RGBA8
, GL_RGBA
, GL_UNSIGNED_BYTE
, true, 4, 1, 1 },
85 { GL_RGBA8_SNORM
, GL_RGBA
, GL_BYTE
, true, 4, 1, 1 },
86 { GL_RG16UI
, GL_RG_INTEGER
, GL_UNSIGNED_SHORT
, true, 4, 1, 1 },
87 { GL_RG16I
, GL_RG_INTEGER
, GL_SHORT
, true, 4, 1, 1 },
88 { GL_RG16
, GL_RG
, GL_UNSIGNED_SHORT
, true, 4, 1, 1 },
89 { GL_RG16_SNORM
, GL_RG
, GL_SHORT
, true, 4, 1, 1 },
90 { GL_R32F
, GL_RED
, GL_FLOAT
, true, 4, 1, 1 },
92 { GL_RGB16UI
, GL_RGB_INTEGER
, GL_UNSIGNED_SHORT
, true, 6, 1, 1 },
93 { GL_RGB16I
, GL_RGB_INTEGER
, GL_SHORT
, true, 6, 1, 1 },
94 { GL_RGB16
, GL_RGB
, GL_UNSIGNED_SHORT
, true, 6, 1, 1 },
95 { GL_RGB16_SNORM
, GL_RGB
, GL_SHORT
, true, 6, 1, 1 },
97 { GL_RGBA16UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_SHORT
, true, 8, 1, 1 },
98 { GL_RGBA16I
, GL_RGBA_INTEGER
, GL_SHORT
, true, 8, 1, 1 },
99 { GL_RGBA16
, GL_RGBA
, GL_UNSIGNED_SHORT
, true, 8, 1, 1 },
100 { GL_RGBA16_SNORM
, GL_RGBA
, GL_SHORT
, true, 8, 1, 1 },
101 { GL_RG32UI
, GL_RG_INTEGER
, GL_UNSIGNED_INT
, true, 8, 1, 1 },
102 { GL_RG32I
, GL_RG_INTEGER
, GL_INT
, true, 8, 1, 1 },
103 { GL_RG32F
, GL_RG
, GL_FLOAT
, true, 8, 1, 1 },
105 { GL_RGB32UI
, GL_RGB_INTEGER
, GL_UNSIGNED_INT
, true, 12, 1, 1 },
106 { GL_RGB32I
, GL_RGB_INTEGER
, GL_INT
, true, 12, 1, 1 },
107 { GL_RGB32F
, GL_RGB
, GL_FLOAT
, true, 12, 1, 1 },
109 { GL_RGBA32UI
, GL_RGBA_INTEGER
, GL_UNSIGNED_INT
, true, 16, 1, 1 },
110 { GL_RGBA32I
, GL_RGBA_INTEGER
, GL_INT
, true, 16, 1, 1 },
111 { GL_RGBA32F
, GL_RGBA
, GL_FLOAT
, true, 16, 1, 1 },
113 { GL_ALPHA
, GL_ALPHA
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
114 { GL_ALPHA8
, GL_ALPHA
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
115 { GL_ALPHA12
, GL_ALPHA
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
116 { GL_ALPHA16
, GL_ALPHA
, GL_UNSIGNED_SHORT
, false, 2, 1, 1 },
118 { GL_LUMINANCE
, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
119 { GL_LUMINANCE8
, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
120 { GL_LUMINANCE12
, GL_LUMINANCE
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
121 { GL_LUMINANCE16
, GL_LUMINANCE
, GL_UNSIGNED_SHORT
, false, 2, 1, 1 },
123 { GL_LUMINANCE_ALPHA
, GL_LUMINANCE_ALPHA
, GL_UNSIGNED_BYTE
, false, 2, 1, 1 },
124 { GL_LUMINANCE8_ALPHA8
, GL_LUMINANCE_ALPHA
, GL_UNSIGNED_BYTE
, false, 2, 1, 1 },
125 { GL_LUMINANCE12_ALPHA12
, GL_LUMINANCE_ALPHA
, GL_UNSIGNED_BYTE
, false, 2, 1, 1 },
126 { GL_LUMINANCE16_ALPHA16
, GL_LUMINANCE_ALPHA
, GL_UNSIGNED_SHORT
, false, 4, 1, 1 },
128 { GL_INTENSITY
, GL_RED
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
129 { GL_INTENSITY8
, GL_RED
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
130 { GL_INTENSITY12
, GL_RED
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
131 { GL_INTENSITY16
, GL_RED
, GL_UNSIGNED_SHORT
, false, 2, 1, 1 },
133 { GL_DEPTH_COMPONENT
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_SHORT
, false, 2, 1, 1 },
134 { GL_DEPTH_COMPONENT16
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_SHORT
, false, 2, 1, 1 },
135 { GL_DEPTH_COMPONENT24
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_SHORT
, false, 2, 1, 1 },
136 { GL_DEPTH_COMPONENT32
, GL_DEPTH_COMPONENT
, GL_UNSIGNED_SHORT
, false, 2, 1, 1 },
138 { GL_DEPTH_STENCIL
, GL_DEPTH_STENCIL
, GL_UNSIGNED_INT_24_8
, false, 4, 1, 1 },
140 { GL_STENCIL_INDEX8
, GL_STENCIL_INDEX
, GL_UNSIGNED_BYTE
, false, 1, 1, 1 },
142 { GL_COMPRESSED_RGB_S3TC_DXT1_EXT
, GL_RED
, GL_BYTE
, true, 8, 4, 4 },
143 { GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
, GL_RED
, GL_BYTE
, true, 8, 4, 4 },
144 { GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
, GL_RED
, GL_BYTE
, true, 16, 4, 4 },
145 { GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
, GL_RED
, GL_BYTE
, true, 16, 4, 4 },
147 { GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
, GL_RED
, GL_BYTE
, true, 8, 4, 4 },
148 { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
, GL_RED
, GL_BYTE
, true, 8, 4, 4 },
149 { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
, GL_RED
, GL_BYTE
, true, 16, 4, 4 },
150 { GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
, GL_RED
, GL_BYTE
, true, 16, 4, 4 },
152 { GL_COMPRESSED_RED_RGTC1
, GL_RED
, GL_BYTE
, true, 8, 4, 4 },
153 { GL_COMPRESSED_SIGNED_RED_RGTC1
, GL_RED
, GL_BYTE
, true, 8, 4, 4 },
155 { GL_COMPRESSED_RG_RGTC2
, GL_RED
, GL_BYTE
, true, 16, 4, 4 },
156 { GL_COMPRESSED_SIGNED_RG_RGTC2
, GL_RED
, GL_BYTE
, true, 16, 4, 4 },
158 { GL_COMPRESSED_RGBA_BPTC_UNORM
, GL_RGBA
, GL_BYTE
, true, 16, 4, 4 },
159 { GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM
, GL_RGB
, GL_BYTE
, true, 16, 4, 4 },
160 { GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT
, GL_RGB
, GL_BYTE
, true, 16, 4, 4 },
161 { GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT
, GL_RGB
, GL_BYTE
, true, 16, 4, 4 },
163 { GL_DEPTH32F_STENCIL8
, GL_DEPTH_STENCIL
, GL_FLOAT_32_UNSIGNED_INT_24_8_REV
, false, 8, 1, 1 },
167 static const struct texture_format
*
168 find_format(const char *str
)
172 const GLenum format
= piglit_get_gl_enum_from_name(str
);
173 for (i
= 0; i
< sizeof(formats
) / sizeof(*formats
); ++i
) {
174 if (format
== formats
[i
].internal_format
) {
179 printf("Unknown format: %s\n", str
);
185 is_format_snorm(const struct texture_format
*format
)
187 switch (format
->internal_format
) {
195 case GL_RGBA16_SNORM
:
203 is_format_compressed(const struct texture_format
*format
)
205 return format
->block_width
!= 1 && format
->block_height
!= 1;
209 is_format_supported(const struct texture_format
*format
)
211 switch (format
->internal_format
) {
212 case GL_COMPRESSED_RED_RGTC1
:
213 case GL_COMPRESSED_SIGNED_RED_RGTC1
:
214 case GL_COMPRESSED_RG_RGTC2
:
215 case GL_COMPRESSED_SIGNED_RG_RGTC2
:
216 return piglit_is_extension_supported("GL_EXT_texture_compression_rgtc");
218 case GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
:
219 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
:
220 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
:
221 case GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
:
222 if (!piglit_is_extension_supported("GL_EXT_texture_sRGB"))
225 case GL_COMPRESSED_RGB_S3TC_DXT1_EXT
:
226 case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
:
227 case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
:
228 case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
:
229 return piglit_is_extension_supported("GL_EXT_texture_compression_s3tc");
231 case GL_COMPRESSED_RGBA_BPTC_UNORM
:
232 case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM
:
233 case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT
:
234 case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT
:
235 return piglit_is_extension_supported("GL_ARB_texture_compression_bptc");
237 case GL_STENCIL_INDEX8
:
238 return piglit_is_extension_supported("GL_ARB_texture_stencil8");
239 case GL_DEPTH32F_STENCIL8
:
240 return piglit_is_extension_supported("GL_ARB_depth_buffer_float");
247 are_formats_compatible(const struct texture_format
*f1
,
248 const struct texture_format
*f2
)
253 if (!f1
->can_be_reinterpreted
|| !f2
->can_be_reinterpreted
)
256 if (is_format_compressed(f1
) && is_format_compressed(f2
)) {
257 /* Compressed-to-compressed copies are not supported */
261 return f1
->bytes
== f2
->bytes
;
264 static const float green
[3] = {0.0, 1.0, 0.0};
266 const struct texture_format
*src_format_arg
, *dst_format_arg
;
267 unsigned char *rand_data
, *src_data
, *dst_data
, *res_data
;
271 piglit_init(int argc
, char **argv
)
274 int i
, Bpp
, rand_data_size
;
277 if (sscanf(argv
[1], "--seed=%d", &seed
) > 0) {
280 } else if (sscanf(argv
[1], "--samples=%d", &samples
) > 0) {
283 } else if (strcmp(argv
[1], "-h") == 0 ||
284 strcmp(argv
[1], "--help") == 0) {
285 printf("usage: arb_copy_image-multisample [--seed=seed] [--samples=samples] [src_format] [dst_format]\n");
296 piglit_require_extension("GL_ARB_copy_image");
297 piglit_require_extension("GL_EXT_framebuffer_object");
298 piglit_require_extension("GL_EXT_texture_integer");
302 piglit_require_extension("GL_ARB_texture_multisample");
303 piglit_require_extension("GL_ARB_sample_shading");
305 glGetIntegerv(GL_MAX_SAMPLES
, &max_samples
);
306 if (samples
> max_samples
) {
307 printf("%d samples not supported\n", samples
);
308 piglit_report_result(PIGLIT_SKIP
);
313 src_format_arg
= find_format(argv
[1]);
314 assert(src_format_arg
!= NULL
);
318 dst_format_arg
= find_format(argv
[2]);
319 assert(dst_format_arg
!= NULL
);
320 assert(dst_format_arg
->bytes
== src_format_arg
->bytes
);
323 /* We now go ahead and generate random data to copy. If we are
324 * dealing with multisampled textures then we generate an array of
325 * images, one image per sample.
328 if (src_format_arg
) {
329 /* Since we know the source format, we know the number of
330 * bits per texel, so we can restrict the amount of random
333 Bpp
= src_format_arg
->bytes
;
335 /* Allocate enough random data for all the tests */
338 rand_data_size
= TEX_SIZE
* TEX_SIZE
* 2 * Bpp
* samples
;
340 rand_data
= malloc(rand_data_size
);
341 src_data
= malloc(rand_data_size
);
342 dst_data
= malloc(rand_data_size
);
343 res_data
= malloc(rand_data_size
);
345 for (i
= 0; i
< rand_data_size
; ++i
)
346 rand_data
[i
] = rand();
350 memcpy_rect(void *src
, int src_stride
, int src_x
, int src_y
,
351 void *dst
, int dst_stride
, int dst_x
, int dst_y
,
352 int width
, int height
, int Bpp
)
356 src
= (char *)src
+ (src_y
* src_stride
) + (src_x
* Bpp
);
357 dst
= (char *)dst
+ (dst_y
* dst_stride
) + (dst_x
* Bpp
);
359 for (i
= 0; i
< height
; ++i
) {
360 memcpy(dst
, src
, width
* Bpp
);
361 src
= (char *)src
+ src_stride
;
362 dst
= (char *)dst
+ dst_stride
;
367 setup_test_data(const struct texture_format
*src_format
,
368 const struct texture_format
*dst_format
)
370 int i
, j
, stride
, image_size
, data_size
;
371 unsigned char *src_image
, *res_image
;
374 stride
= TEX_SIZE
* src_format
->bytes
;
375 image_size
= stride
* TEX_SIZE
;
376 data_size
= image_size
* samples
;
378 if (src_format
->data_type
== GL_FLOAT
||
379 dst_format
->data_type
== GL_FLOAT
) {
380 /* If it's a floating-point type, let's avoid using invalid
381 * floating-point values. That might throw things off */
382 float *src_float
= (float *)src_data
;
383 float *dst_float
= (float *)dst_data
;
385 rand_int
= (int *)rand_data
;
386 for (i
= 0; i
< data_size
/ sizeof(float); ++i
)
387 src_float
[i
] = rand_int
[i
] / (float)INT16_MAX
;
389 rand_int
= (int *)(rand_data
+ data_size
);
390 for (i
= 0; i
< data_size
/ sizeof(float); ++i
)
391 dst_float
[i
] = rand_int
[i
] / (float)INT16_MAX
;
393 else if (src_format
->data_type
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
||
394 dst_format
->data_type
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
) {
395 /* Use float values in [0,1]. The stencil values will
396 * be the least significant 8 bits in the dwords at odd
398 float *src_float
= (float *)src_data
;
399 float *dst_float
= (float *)dst_data
;
400 rand_int
= (int *)rand_data
;
401 for (i
= 0; i
< data_size
/ sizeof(float); ++i
) {
402 src_float
[i
] = (rand_int
[i
] & 0xffff) / 65535.0f
;
403 assert(src_float
[i
] <= 1.0f
);
405 rand_int
= (int *)(rand_data
+ data_size
);
406 for (i
= 0; i
< data_size
/ sizeof(float); ++i
) {
407 dst_float
[i
] = (rand_int
[i
] & 0xffff) / 65535.0f
;
408 assert(dst_float
[i
] <= 1.0f
);
411 memcpy(src_data
, rand_data
, data_size
);
412 memcpy(dst_data
, rand_data
+ data_size
, data_size
);
415 if (is_format_snorm(src_format
) || is_format_snorm(dst_format
)) {
416 /* In this case, certain values, namely INT_MIN are
417 * are disallowed and may be clampped.
419 if (src_format
->data_type
== GL_BYTE
||
420 dst_format
->data_type
== GL_BYTE
) {
421 GLbyte
*bytes
= (GLbyte
*)src_data
;
422 for (i
= 0; i
< data_size
/ sizeof(*bytes
); ++i
)
423 if (bytes
[i
] == -128)
426 bytes
= (GLbyte
*)dst_data
;
427 for (i
= 0; i
< data_size
/ sizeof(*bytes
); ++i
)
428 if (bytes
[i
] == -128)
430 } else if (src_format
->data_type
== GL_SHORT
||
431 dst_format
->data_type
== GL_SHORT
) {
432 GLshort
*shorts
= (GLshort
*)src_data
;
433 for (i
= 0; i
< data_size
/ sizeof(*shorts
); ++i
)
434 if (shorts
[i
] == -32768)
437 shorts
= (GLshort
*)dst_data
;
438 for (i
= 0; i
< data_size
/ sizeof(*shorts
); ++i
)
439 if (shorts
[i
] == -32768)
442 assert(!"Invalid data type for SNORM format");
446 /* Creates the expected result image from the source and
447 * destination images. The middle TEX_SIZE/2 x TEX_SIZE/2 pixels
448 * should come from src_data while the rest should come from
449 * dest_data. If samples > 1, then, since CopyImageSubData copies
450 * all the samples, we need to copy the center of every plane.
453 /* Copy all of dst_data to result */
454 memcpy(res_data
, dst_data
, data_size
);
455 for (j
= 0; j
< samples
; ++j
) {
456 src_image
= src_data
+ (j
* image_size
);
457 res_image
= res_data
+ (j
* image_size
);
458 /* Copy the center TEX_SIZE/2 x TEX_SIZE/2 pixels forms
459 * src_data to res_data
461 memcpy_rect(src_image
, stride
, TEX_SIZE
/4, TEX_SIZE
/4,
462 res_image
, stride
, TEX_SIZE
/4, TEX_SIZE
/4,
463 TEX_SIZE
/2, TEX_SIZE
/2, src_format
->bytes
);
465 /* Copy the upper-left corner of the result to the
466 * lower-right of the result
468 memcpy_rect(res_image
, stride
, 0, TEX_SIZE
/2,
469 res_image
, stride
, TEX_SIZE
/2, 0,
470 TEX_SIZE
/2, TEX_SIZE
/2, src_format
->bytes
);
474 const char ms_compare_vs_source
[] =
477 "out vec2 tex_coords;\n"
480 " tex_coords = vertex;\n"
481 " vec2 pos = (vertex.xy * 2) - vec2(1, 1);\n"
482 " gl_Position = vec4(pos, 0, 1);\n"
485 const char ms_compare_fs_source
[] =
487 "#extension GL_ARB_texture_multisample : enable\n"
488 "in vec2 tex_coords;\n"
489 "uniform %ssampler2DMS tex1;\n"
490 "uniform %ssampler2DMS tex2;\n"
491 "uniform ivec2 tex_size;\n"
492 "uniform int samples;\n"
493 "const vec4 red = vec4(1, 0, 0, 1);\n"
494 "const vec4 green = vec4(0, 1, 0, 1);\n"
498 " ivec2 tex_px = ivec2(tex_coords * tex_size);\n"
499 " for (int i = 0; i < samples; ++i) {\n"
500 " %svec4 val1 = texelFetch(tex1, tex_px, i);\n"
501 " %svec4 val2 = texelFetch(tex2, tex_px, i);\n"
502 " if (val1 == val2)\n"
505 " gl_FragColor = mix(red, green, float(count) / float(samples));\n"
509 load_compare_program(const struct texture_format
*format
)
517 } comp
, ucomp
, icomp
, *compare
;
518 char *fs_src
, *gtype
;
520 switch (format
->format
) {
524 case GL_RGBA_INTEGER
:
525 case GL_BGRA_INTEGER
:
526 case GL_STENCIL_INDEX
:
527 switch (format
->data_type
) {
533 case GL_UNSIGNED_BYTE
:
534 case GL_UNSIGNED_SHORT
:
535 case GL_UNSIGNED_INT
:
539 assert(!"Invalid data type");
549 case GL_LUMINANCE_ALPHA
:
551 case GL_DEPTH_COMPONENT
:
555 assert(!"Invalid Format");
558 if (!compare
->prog
) {
559 if (compare
== &comp
) {
561 } else if (compare
== &ucomp
) {
563 } else if (compare
== &icomp
) {
566 assert(!"Invalid comparison function");
570 /* The generated source will be shorter because we replace
571 * a bunch of "%s" with "u", "i", or ""
573 fs_src
= malloc(sizeof(ms_compare_fs_source
));
574 snprintf(fs_src
, sizeof(ms_compare_fs_source
),
575 ms_compare_fs_source
, gtype
, gtype
, gtype
, gtype
);
577 compare
->prog
= piglit_build_simple_program_unlinked(
578 ms_compare_vs_source
, fs_src
);
579 glBindAttribLocation(compare
->prog
, 0, "vertex");
580 glLinkProgram(compare
->prog
);
581 piglit_link_check_status(compare
->prog
);
585 compare
->tex1
= glGetUniformLocation(compare
->prog
, "tex1");
586 compare
->tex2
= glGetUniformLocation(compare
->prog
, "tex2");
587 compare
->tex_size
= glGetUniformLocation(compare
->prog
, "tex_size");
588 compare
->samples
= glGetUniformLocation(compare
->prog
, "samples");
591 glUseProgram(compare
->prog
);
592 glUniform1i(compare
->tex1
, 0);
593 glUniform1i(compare
->tex2
, 1);
594 glUniform2i(compare
->tex_size
, TEX_SIZE
, TEX_SIZE
);
595 glUniform1i(compare
->samples
, samples
);
598 static enum piglit_result
599 run_multisample_test(const struct texture_format
*src_format
,
600 const struct texture_format
*dst_format
)
603 int fbo_width
, fbo_height
;
604 GLuint fbo
, rb
, src_tex
, dst_tex
, res_tex
;
605 static const GLfloat verts
[] = {
614 /* Upload the source, destination, and expected result */
615 src_tex
= piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE
, 0,
616 src_format
->internal_format
,
617 TEX_SIZE
, TEX_SIZE
, 1, samples
,
619 src_format
->data_type
, src_data
);
621 dst_tex
= piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE
, 0,
622 dst_format
->internal_format
,
623 TEX_SIZE
, TEX_SIZE
, 1, samples
,
625 dst_format
->data_type
, dst_data
);
627 res_tex
= piglit_multisample_texture(GL_TEXTURE_2D_MULTISAMPLE
, 0,
628 dst_format
->internal_format
,
629 TEX_SIZE
, TEX_SIZE
, 1, samples
,
631 dst_format
->data_type
, res_data
);
632 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
634 /* If any of these are zero, but there was no error, then it must
635 * not be renderable, so we just skip without even reporting the
638 if ((src_tex
== 0 || dst_tex
== 0 || res_tex
== 0) && pass
)
641 glCopyImageSubData(src_tex
, GL_TEXTURE_2D_MULTISAMPLE
, 0,
642 TEX_SIZE
/ 4, TEX_SIZE
/ 4, 0,
643 dst_tex
, GL_TEXTURE_2D_MULTISAMPLE
, 0,
644 TEX_SIZE
/ 4, TEX_SIZE
/ 4, 0,
645 TEX_SIZE
/ 2, TEX_SIZE
/ 2, 1);
646 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
648 glCopyImageSubData(dst_tex
, GL_TEXTURE_2D_MULTISAMPLE
, 0,
650 dst_tex
, GL_TEXTURE_2D_MULTISAMPLE
, 0,
652 TEX_SIZE
/ 2, TEX_SIZE
/ 2, 1);
653 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
655 if (piglit_automatic
) {
656 fbo_width
= TEX_SIZE
;
657 fbo_height
= TEX_SIZE
;
658 glGenFramebuffers(1, &fbo
);
659 glBindFramebuffer(GL_FRAMEBUFFER
, fbo
);
661 glGenRenderbuffers(1, &rb
);
662 glBindRenderbuffer(GL_RENDERBUFFER
, rb
);
663 glRenderbufferStorage(GL_RENDERBUFFER
, GL_RGBA
,
664 fbo_width
, fbo_height
);
665 glFramebufferRenderbuffer(GL_FRAMEBUFFER
,
666 GL_COLOR_ATTACHMENT0
,
667 GL_RENDERBUFFER
, rb
);
669 fbo_width
= piglit_width
;
670 fbo_height
= piglit_height
;
671 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
673 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
674 glViewport(0, 0, fbo_width
, fbo_height
);
676 glClearColor(1.0f
, 0.0f
, 1.0f
, 1.0f
);
677 glClear(GL_COLOR_BUFFER_BIT
);
679 /* Now we use a comparison shader to check to see if the
680 * destination matches the expected result.
682 glActiveTexture(GL_TEXTURE0
);
683 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
, dst_tex
);
684 glActiveTexture(GL_TEXTURE1
);
685 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
, res_tex
);
687 load_compare_program(dst_format
);
688 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
690 glEnableVertexAttribArray(0);
691 glVertexAttribPointer(0, 2, GL_FLOAT
, GL_FALSE
, 0, verts
);
692 glDrawArrays(GL_TRIANGLES
, 0, 6);
693 glDisableVertexAttribArray(0);
694 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
696 /* If the destination texture matches the expected result, we
697 * should get green. If not, we get red and this test fails.
699 pass
&= piglit_probe_rect_rgb(0, 0, fbo_width
, fbo_height
, green
);
701 glDeleteTextures(1, &src_tex
);
702 glDeleteTextures(1, &dst_tex
);
703 glDeleteTextures(1, &res_tex
);
705 if (!piglit_automatic
)
706 piglit_present_results();
708 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
712 /** test if two pixels are equal, according to the format */
714 pixels_equal(const void *p1
, const void *p2
,
715 const struct texture_format
*format
)
717 if (format
->data_type
== GL_FLOAT_32_UNSIGNED_INT_24_8_REV
) {
718 /* don't compare the 3 unused bytes which pad the
721 const float *f1
= (const float *) p1
;
722 const float *f2
= (const float *) p2
;
723 const GLuint
*b1
= (const GLuint
*) p1
;
724 const GLuint
*b2
= (const GLuint
*) p2
;
727 if ((b1
[1] & 0xff) != (b2
[1] & 0xff))
732 return memcmp(p1
, p2
, format
->bytes
) == 0;
738 check_texture(GLuint texture
, unsigned level
,
739 const struct texture_format
*format
, const unsigned char *data
)
743 unsigned char *tex_data
;
745 tex_data
= malloc(TEX_SIZE
* TEX_SIZE
* format
->bytes
);
747 glBindTexture(GL_TEXTURE_2D
, texture
);
748 if (format
->block_width
!= 1 || format
->block_height
!= 1) {
750 glGetCompressedTexImage(GL_TEXTURE_2D
, level
, tex_data
);
752 glGetTexImage(GL_TEXTURE_2D
, level
, format
->format
,
753 format
->data_type
, tex_data
);
756 for (j
= 0; j
< TEX_SIZE
; ++j
) {
757 for (i
= 0; i
< TEX_SIZE
; ++i
) {
758 int pos
= ((j
* TEX_SIZE
) + i
) * format
->bytes
;
759 if (!pixels_equal(tex_data
+ pos
, data
+ pos
, format
)) {
760 fprintf(stdout
, "texel mismatch at (%d, %d); expected 0x",
762 for (k
= format
->bytes
- 1; k
>= 0; --k
)
763 fprintf(stdout
, "%02x", data
[pos
+ k
]);
765 fprintf(stdout
, ", received 0x");
766 for (k
= format
->bytes
- 1; k
>= 0; --k
)
767 fprintf(stdout
, "%02x", tex_data
[pos
+ k
]);
768 fprintf(stdout
, ".\n");
771 i
= j
= TEX_SIZE
; /* exit loops upon error */
781 static enum piglit_result
782 run_test(const struct texture_format
*src_format
,
783 const struct texture_format
*dst_format
)
785 bool pass
= true, warn
= false;
786 unsigned src_width
, src_height
, dst_width
, dst_height
;
787 unsigned src_level
, dst_level
;
790 glEnable(GL_TEXTURE_2D
);
792 glGenTextures(2, texture
);
794 src_width
= TEX_SIZE
* src_format
->block_width
;
795 src_height
= TEX_SIZE
* src_format
->block_height
;
797 glBindTexture(GL_TEXTURE_2D
, texture
[0]);
798 if (src_format
->can_be_reinterpreted
) {
799 src_level
= DEFAULT_SRC_LEVEL
;
800 glTexStorage2D(GL_TEXTURE_2D
, src_level
+ 2,
801 src_format
->internal_format
,
802 src_width
<< src_level
, src_height
<< src_level
);
803 if (src_format
->block_width
!= 1 ||
804 src_format
->block_height
!= 1) {
806 glCompressedTexSubImage2D(GL_TEXTURE_2D
, src_level
,
808 src_width
, src_height
,
809 src_format
->internal_format
,
810 TEX_SIZE
* TEX_SIZE
* src_format
->bytes
,
813 glTexSubImage2D(GL_TEXTURE_2D
, src_level
, 0, 0,
814 src_width
, src_height
, src_format
->format
,
815 src_format
->data_type
, src_data
);
819 /* All non-reintepretable textures are uncompressed */
820 glTexImage2D(GL_TEXTURE_2D
, 0, src_format
->internal_format
,
821 src_width
, src_height
, 0, src_format
->format
,
822 src_format
->data_type
, src_data
);
824 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
825 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
826 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
830 warn
|= !check_texture(texture
[0], src_level
, src_format
, src_data
);
832 dst_width
= TEX_SIZE
* dst_format
->block_width
;
833 dst_height
= TEX_SIZE
* dst_format
->block_height
;
835 glBindTexture(GL_TEXTURE_2D
, texture
[1]);
836 if (dst_format
->can_be_reinterpreted
) {
837 dst_level
= DEFAULT_DST_LEVEL
;
838 glTexStorage2D(GL_TEXTURE_2D
, dst_level
+ 2,
839 dst_format
->internal_format
,
840 dst_width
<< dst_level
, dst_height
<< dst_level
);
841 if (dst_format
->block_width
!= 1 ||
842 dst_format
->block_height
!= 1) {
844 glCompressedTexSubImage2D(GL_TEXTURE_2D
, dst_level
,
846 dst_width
, dst_height
,
847 dst_format
->internal_format
,
848 TEX_SIZE
* TEX_SIZE
* dst_format
->bytes
,
851 glTexSubImage2D(GL_TEXTURE_2D
, dst_level
, 0, 0,
852 dst_width
, dst_height
, dst_format
->format
,
853 dst_format
->data_type
, dst_data
);
857 /* All non-reintepritable textures are uncompressed */
858 glTexImage2D(GL_TEXTURE_2D
, 0, dst_format
->internal_format
,
859 dst_width
, dst_height
, 0, dst_format
->format
,
860 dst_format
->data_type
, dst_data
);
862 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
863 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
864 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
868 warn
|= !check_texture(texture
[1], dst_level
, dst_format
, dst_data
);
870 glCopyImageSubData(texture
[0], GL_TEXTURE_2D
, src_level
,
871 src_width
/ 4, src_height
/ 4, 0,
872 texture
[1], GL_TEXTURE_2D
, dst_level
,
873 dst_width
/ 4, dst_height
/ 4, 0,
874 src_width
/ 2, src_height
/ 2, 1);
875 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
877 glCopyImageSubData(texture
[1], GL_TEXTURE_2D
, dst_level
,
878 0, dst_height
/ 2, 0,
879 texture
[1], GL_TEXTURE_2D
, dst_level
,
881 dst_width
/ 2, dst_height
/ 2, 1);
882 pass
&= piglit_check_gl_error(GL_NO_ERROR
);
884 pass
&= check_texture(texture
[1], dst_level
, dst_format
, res_data
);
887 glDeleteTextures(2, texture
);
889 glDisable(GL_TEXTURE_2D
);
891 return pass
? (warn
? PIGLIT_WARN
: PIGLIT_PASS
) : PIGLIT_FAIL
;
897 enum piglit_result result
= PIGLIT_PASS
;
898 enum piglit_result subtest
;
899 const struct texture_format
*src_format_list
, *dst_format_list
;
900 const struct texture_format
*src_format
, *dst_format
;
901 int sf
, df
, src_format_count
, dst_format_count
;
903 if (src_format_arg
) {
904 src_format_list
= src_format_arg
;
905 src_format_count
= 1;
907 src_format_list
= formats
;
908 src_format_count
= ARRAY_SIZE(formats
);
911 if (dst_format_arg
) {
912 dst_format_list
= dst_format_arg
;
913 dst_format_count
= 1;
915 dst_format_list
= formats
;
916 dst_format_count
= ARRAY_SIZE(formats
);
919 for (sf
= 0; sf
< src_format_count
; ++sf
) {
920 src_format
= &src_format_list
[sf
];
921 if (!is_format_supported(src_format
))
923 const char *src_name
=
924 piglit_get_gl_enum_name(src_format
->internal_format
);
926 for (df
= 0; df
< dst_format_count
; ++df
) {
927 dst_format
= &dst_format_list
[df
];
928 if (!is_format_supported(dst_format
))
930 if (!are_formats_compatible(src_format
, dst_format
))
932 const char *dst_name
= piglit_get_gl_enum_name(
933 dst_format
->internal_format
);
935 setup_test_data(src_format
, dst_format
);
937 subtest
= run_test(src_format
,
940 if (is_format_compressed(src_format
) ||
941 is_format_compressed(dst_format
))
944 subtest
= run_multisample_test(src_format
,
948 if (!src_format_arg
) {
949 /* In this case, we're running a full suite
950 * of subtests, report accordingly.
952 piglit_report_subtest_result(subtest
,
953 "Source: %s/Destination: %s",
955 } else if (!dst_format_arg
) {
956 /* In this case, the source format was
957 * specified but the destination was not.
958 * Report one subtest per destination.
960 piglit_report_subtest_result(subtest
,
961 "Destination Format: %s",
965 if (subtest
== PIGLIT_FAIL
)
966 result
= PIGLIT_FAIL
;
967 else if (subtest
== PIGLIT_WARN
&& result
== PIGLIT_PASS
)
968 result
= PIGLIT_WARN
;