2 * Copyright © 2012 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
27 * Verify the proper functioning of multisample antialiasing for all
28 * possible buffer formats.
30 * This test operates by rendering an MSAA image twice: once in a
31 * standard RGBA buffer (the behaviour of which is well tested by the
32 * other MSAA tests), and once in a buffer with some other format.
33 * Then it blits both images to corresponding single-sample buffers
34 * and uses glReadPixels to make sure the same image was drawn in both
35 * cases (to within the expected tolerance considering the bit depth
38 * Finally, the images that were compared are drawn on screen to make
39 * it easier to diagnose failures.
41 * When testing sRGB formats, the reference image is rendered using
42 * SRGB8_ALPHA8 format rather than RGBA format (SRGB8_ALPHA8 format is
43 * also well tested by the other MSAA tests).
47 #include "../../fbo/fbo-formats.h"
48 using namespace piglit_util_fbo
;
49 using namespace piglit_util_test_pattern
;
51 PIGLIT_GL_TEST_CONFIG_BEGIN
53 config
.supports_gl_compat_version
= 10;
55 config
.window_width
= 512;
56 config
.window_height
= 256;
57 config
.window_visual
= PIGLIT_GL_VISUAL_DOUBLE
| PIGLIT_GL_VISUAL_RGBA
;
58 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
60 PIGLIT_GL_TEST_CONFIG_END
64 const int pattern_width
= 256; const int pattern_height
= 256;
66 bool all_samples
= false;
70 ColorGradientSunburst
*test_pattern_vec4
;
71 ColorGradientSunburst
*test_pattern_ivec4
;
72 ColorGradientSunburst
*test_pattern_uvec4
;
74 struct int_resolve_check_s
{
81 const char int_resolve_check_vs
[] =
83 "in vec4 piglit_vertex;\n"
85 " gl_Position = piglit_vertex;\n"
88 /* The OpenGL ES 3.2 and OpenGL 4.4 specs both state:
90 * "If the source formats are integer types or stencil values, a
91 * single sample's value is selected for each pixel."
93 * This shader checks exactly that condition, namely that the result of the
94 * resolve is exactly one of the sample values in the original image.
96 const char int_resolve_check_fs
[] =
98 "#extension GL_ARB_texture_multisample: require\n"
99 "uniform isampler2DMS msaa;\n"
100 "uniform isampler2D resolve;\n"
101 "uniform int samples;\n"
103 " gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);\n"
104 " const vec4 green = vec4(0.0, 1.0, 0.0, 1.0);\n"
105 " ivec2 pos = ivec2(gl_FragCoord.xy);\n"
106 " ivec4 res = texelFetch(resolve, pos, 0);\n"
107 " for (int s = 0; s < samples; s++) {\n"
108 " if (res == texelFetch(msaa, pos, s)) {\n"
109 " gl_FragColor = green;\n"
116 * This class encapsulates the code necessary to draw the test pattern
117 * in either the reference GL_RGBA format or the format under test,
118 * downsample it, read the rendered pixels into memory, and draw a
119 * visualization of the result.
121 class PatternRenderer
124 bool try_setup(GLenum internalformat
, bool is_integer
);
125 void set_piglit_tolerance();
126 void set_color_clamping_mode();
128 float *read_image(GLenum base_format
);
131 * Number of bits in each color channel. E.g. color_bits[2]
132 * == number of bits in blue color channel.
137 * Type of data in the color buffer. E.g. GL_FLOAT,
138 * GL_UNSIGNED_NORMALIZED, or GL_UNSIGNED_INT.
140 GLenum component_type
;
143 * True if the color buffer uses an sRGB format.
148 * ColorGradientSunburst object that will be used to draw the
151 ColorGradientSunburst
*test_pattern
;
154 * Color offset that will be used to draw the test pattern.
159 * Color scale factor that will be used to draw the test
165 * Color clamping setting that should be used for this test.
166 * Normally GL_FIXED_ONLY (the default setting) works fine,
167 * however the GL spec mandates that signed normalized formats
168 * be clamped to [0, 1] when in GL_FIXED_ONLY mode. So when
169 * testing signed normalized formats, this is GL_FALSE.
171 GLenum color_clamping_mode
;
179 * Try to set up the necessary framebuffers to render to the given
180 * MSAA format. Return false if one or more of the framebuffers is
184 PatternRenderer::try_setup(GLenum internalformat
, bool is_integer
)
186 FboConfig
config_downsampled(0, pattern_width
, pattern_height
);
187 config_downsampled
.color_internalformat
= internalformat
;
190 config_downsampled
.color_format
= GL_RGBA_INTEGER
;
191 config_downsampled
.num_rb_attachments
= 0;
192 config_downsampled
.num_tex_attachments
= 1;
193 config_downsampled
.use_rect
= false;
196 FboConfig config_msaa
= config_downsampled
;
197 config_msaa
.num_samples
= num_samples
;
199 if (!(fbo_downsampled
.try_setup(config_downsampled
) &&
200 fbo_msaa
.try_setup(config_msaa
)))
203 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fbo_downsampled
.handle
);
204 glGetFramebufferAttachmentParameteriv(
205 GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
206 GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE
, &color_bits
[0]);
207 glGetFramebufferAttachmentParameteriv(
208 GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
209 GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE
, &color_bits
[1]);
210 glGetFramebufferAttachmentParameteriv(
211 GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
212 GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE
, &color_bits
[2]);
213 glGetFramebufferAttachmentParameteriv(
214 GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
215 GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE
, &color_bits
[3]);
216 glGetFramebufferAttachmentParameteriv(
217 GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
218 GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE
,
219 (GLint
*) &component_type
);
221 piglit_get_luminance_intensity_bits(internalformat
, color_bits
);
224 for (int i
= 0; i
< 4 && !num_bits
; i
++)
225 num_bits
= color_bits
[i
];
227 printf("Red, green, blue, and alpha sizes are all zero.\n");
231 color_clamping_mode
= GL_FIXED_ONLY
;
232 switch (component_type
) {
234 assert(test_pattern_ivec4
);
235 test_pattern
= test_pattern_ivec4
;
236 color_offset
= 1.0 - pow(2.0, num_bits
- 1);
237 color_scale
= -2.0 * color_offset
;
239 case GL_UNSIGNED_INT
:
240 assert(test_pattern_uvec4
);
241 test_pattern
= test_pattern_uvec4
;
242 color_scale
= pow(2.0, num_bits
) - 1.0;
245 case GL_UNSIGNED_NORMALIZED
:
246 test_pattern
= test_pattern_vec4
;
251 /* Test floating point formats to a (rather arbitrary)
252 * range of [-10.0, 10.0], to make sure no extraneous
253 * clamping occurs. Exception: GL_R11F_G11F_B10F_EXT
254 * and GL_RGB9_E5_EXT are unsigned, so they are tested
255 * to a range of [0.0, 10.0].
257 test_pattern
= test_pattern_vec4
;
258 if (internalformat
== GL_R11F_G11F_B10F_EXT
||
259 internalformat
== GL_RGB9_E5_EXT
) {
263 color_offset
= -10.0;
267 case GL_SIGNED_NORMALIZED
:
268 test_pattern
= test_pattern_vec4
;
271 color_clamping_mode
= GL_FALSE
;
274 printf("Unrecognized component type: %s\n",
275 piglit_get_gl_enum_name(component_type
));
276 piglit_report_result(PIGLIT_FAIL
);
279 GLint color_encoding
;
280 glGetFramebufferAttachmentParameteriv(
281 GL_READ_FRAMEBUFFER
, GL_COLOR_ATTACHMENT0
,
282 GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING
, &color_encoding
);
283 is_srgb
= color_encoding
== GL_SRGB
;
290 * Return the number of mantissa bits available in an n-bit floating
294 get_mantissa_bits(int n
)
301 case 0: return 0; /* Unused channel */
303 printf("Unrecognized floating point format (%d bits)\n", n
);
304 piglit_report_result(PIGLIT_FAIL
);
311 * Set the piglit tolerance appropriately based on the number of bits
314 void PatternRenderer::set_piglit_tolerance()
316 int tolerance_bits
[4];
318 for (int i
= 0; i
< 4; ++i
) {
319 int bits
= color_bits
[i
];
320 if (component_type
== GL_FLOAT
) {
321 /* We only want to count mantissa bits for the
322 * purpose of setting the test tolerance.
324 bits
= get_mantissa_bits(bits
);
327 /* For channels that have 0 bits, test to 8
328 * bits precision so we can verify that the
329 * blit puts in the appropriate value.
331 tolerance_bits
[i
] = 8;
332 } else if (bits
> 8) {
333 /* For channels that have >8 bits, test to 8
334 * bits precision because we only use an 8-bit
337 tolerance_bits
[i
] = 8;
339 tolerance_bits
[i
] = bits
;
343 piglit_set_tolerance_for_bits(tolerance_bits
[0], tolerance_bits
[1],
344 tolerance_bits
[2], tolerance_bits
[3]);
349 * Set up the appropriate color clamping mode for testing this format.
352 PatternRenderer::set_color_clamping_mode()
354 glClampColor(GL_CLAMP_FRAGMENT_COLOR
, color_clamping_mode
);
355 glClampColor(GL_CLAMP_READ_COLOR
, color_clamping_mode
);
360 * Draw the test pattern into the MSAA framebuffer, and then blit it
361 * to the downsampled FBO to force an MSAA resolve.
364 PatternRenderer::draw()
366 /* Draw into the MSAA fbo */
367 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbo_msaa
.handle
);
368 fbo_msaa
.set_viewport();
369 set_color_clamping_mode();
370 test_pattern
->draw_with_scale_and_offset(TestPattern::no_projection
,
371 color_scale
, color_offset
);
373 /* Blit to the downsampled fbo, forcing the image to be downsampled */
374 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fbo_msaa
.handle
);
375 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, fbo_downsampled
.handle
);
376 glBlitFramebuffer(0, 0, pattern_width
, pattern_height
,
377 0, 0, pattern_width
, pattern_height
,
378 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
383 * Return the integer base format corresponding to a given base
387 integer_base_format(GLenum base_format
)
389 switch (base_format
) {
391 return GL_RED_INTEGER_EXT
;
393 return GL_RG_INTEGER
;
395 return GL_RGB_INTEGER
;
397 return GL_RGBA_INTEGER
;
399 return GL_ALPHA_INTEGER
;
401 return GL_LUMINANCE_INTEGER_EXT
;
402 case GL_LUMINANCE_ALPHA
:
403 return GL_LUMINANCE_ALPHA_INTEGER_EXT
;
405 printf("Unexpected integer base_format: %s\n",
406 piglit_get_gl_enum_name(base_format
));
407 piglit_report_result(PIGLIT_FAIL
);
414 * Read the image from the downsampled FBO into a newly allocated
415 * array of floats and return it.
418 PatternRenderer::read_image(GLenum base_format
)
420 unsigned components
= piglit_num_components(base_format
);
421 unsigned array_size
= components
*pattern_width
*pattern_height
;
422 float *image
= (float *) malloc(sizeof(float)*array_size
);
423 glBindFramebuffer(GL_READ_FRAMEBUFFER
, fbo_downsampled
.handle
);
424 set_color_clamping_mode();
425 if (base_format
== GL_INTENSITY
) {
426 /* GL_INTENSITY is not allowed for ReadPixels so
427 * substitute GL_LUMINANCE.
429 base_format
= GL_LUMINANCE
;
431 if (component_type
== GL_INT
|| component_type
== GL_UNSIGNED_INT
) {
432 int *tmp
= (int *) malloc(sizeof(int)*array_size
);
433 glReadPixels(0, 0, pattern_width
, pattern_height
,
434 integer_base_format(base_format
),
435 component_type
, tmp
);
436 if (component_type
== GL_INT
) {
437 for (unsigned i
= 0; i
< array_size
; ++i
)
440 for (unsigned i
= 0; i
< array_size
; ++i
)
441 image
[i
] = (unsigned) tmp
[i
];
445 glReadPixels(0, 0, pattern_width
, pattern_height
, base_format
,
448 for (unsigned i
= 0; i
< array_size
; ++i
)
449 image
[i
] = (image
[i
] - color_offset
) / color_scale
;
455 * PatternRenderer used to render the image under test.
457 PatternRenderer test_renderer
;
461 * PatternRenderer used to render the reference image (in GL_RGBA
464 PatternRenderer ref_renderer
;
468 * Transform the reference image (which is in GL_RGBA format) to an
469 * expected image for a given base internal format, using the the
470 * transformation described in the GL 3.0 spec, table 3.15 (Conversion
471 * from RGBA, depth, and stencil pixel components to internal texture,
472 * table, or filter components). In short, the mapping is as follows:
474 * base_internal_format mapping
476 * GL_LUMINANCE R -> L
477 * GL_LUMINANCE_ALPHA R,A -> L,A
478 * GL_INTENSITY R -> I
481 * GL_RGB R,G,B -> R,G,B
482 * GL_RGBA R,G,B,A -> R,G,B,A
485 compute_expected_image(const float *ref_image
, GLenum base_internal_format
)
487 unsigned components
= piglit_num_components(base_internal_format
);
488 unsigned num_pixels
= pattern_width
*pattern_height
;
489 unsigned size
= sizeof(float)*components
*num_pixels
;
490 float *expected_image
= (float *) malloc(size
);
491 for (unsigned i
= 0; i
< num_pixels
; ++i
) {
492 float *expected
= &expected_image
[components
*i
];
493 const float *ref
= &ref_image
[4*i
];
494 for (unsigned j
= 0; j
< components
; ++j
) {
495 switch (base_internal_format
) {
497 expected
[j
] = ref
[3];
499 case GL_LUMINANCE_ALPHA
:
500 expected
[j
] = ref
[j
? 3 : 0];
503 expected
[j
] = ref
[j
];
508 return expected_image
;
513 * Test a given internal format.
516 test_format(const struct format_desc
*format
)
520 if (format
->internalformat
== 3 ||
521 format
->internalformat
== 4) {
525 /* Caller messes with the clear color. Reset it to the
528 glClearColor(0, 0, 0, 0);
530 printf("Testing %s\n", get_format_name(format
->internalformat
));
532 /* Set up the framebuffers for rendering the test image. This
533 * might fail if the format we're testing isn't supported as a
534 * render target, and that's ok.
536 * Note: in order to be sure we test all formats which the
537 * implementations supports as render targets, we try all of
538 * them, even formats that the spec doesn't define as
539 * color-renderable (e.g. GL_LUMINANCE8, which is supported as
540 * a render target format by some drivers even though it's not
541 * officially color-renderable). If we tried to request a
542 * color-renderable format and it wasn't supported, we would
543 * expect the framebuffer to be incomplete. If we tried to
544 * request a non-color-renderable format and it wasn't
545 * supported, we might have received a GL error. In either
546 * case just skip to the next format.
548 bool is_integer
= (test_sets
[test_index
].basetype
== GL_INT
);
549 bool setup_success
= test_renderer
.try_setup(format
->internalformat
,
551 if (glGetError() != GL_NO_ERROR
) {
552 printf("Error setting up test renderbuffers\n");
555 if (!setup_success
) {
556 printf("Unsupported framebuffer combination\n");
560 /* Set up the framebuffers for rendering the reference image.
561 * This shouldn't fail.
563 setup_success
= ref_renderer
.try_setup(test_renderer
.is_srgb
?
564 GL_SRGB8_ALPHA8
: GL_RGBA
,
566 if (!piglit_check_gl_error(GL_NO_ERROR
)) {
567 printf("Error setting up reference renderbuffers\n");
570 if (!setup_success
) {
571 printf("Reference framebuffer combination is unsupported\n");
575 test_renderer
.draw();
577 test_renderer
.read_image(format
->base_internal_format
);
581 compare_fbo
.setup(FboConfig(0, pattern_width
, pattern_height
));
583 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, compare_fbo
.handle
);
585 glUseProgram(int_resolve_check
.prog
);
586 glUniform1i(int_resolve_check
.u_msaa
, 0);
587 glUniform1i(int_resolve_check
.u_resolve
, 1);
588 glUniform1i(int_resolve_check
.u_samples
, num_samples
);
590 glActiveTexture(GL_TEXTURE0
);
591 glBindTexture(GL_TEXTURE_2D_MULTISAMPLE
,
592 test_renderer
.fbo_msaa
.color_tex
[0]);
594 glActiveTexture(GL_TEXTURE1
);
595 glBindTexture(GL_TEXTURE_2D
,
596 test_renderer
.fbo_downsampled
.color_tex
[0]);
598 glViewport(0, 0, pattern_width
, pattern_height
);
599 piglit_draw_rect(-1.0, -1.0, 2.0, 2.0);
601 glBindFramebuffer(GL_READ_FRAMEBUFFER
, compare_fbo
.handle
);
603 const float green
[] = { 0.0, 1.0, 0.0, 1.0 };
604 pass
= piglit_probe_rect_rgb(0, 0, pattern_width
,
605 pattern_height
, green
);
607 /* Show both the test image and the check result on screen
608 * so that the user can diagnose problems.
610 glViewport(0, 0, piglit_width
, piglit_height
);
611 piglit_visualize_image(test_image
, format
->base_internal_format
,
612 pattern_width
, pattern_height
,
616 glBindFramebuffer(GL_READ_FRAMEBUFFER
, compare_fbo
.handle
);
617 glBindFramebuffer(GL_DRAW_FRAMEBUFFER
, piglit_winsys_fbo
);
618 glBlitFramebuffer(0, 0, pattern_width
, pattern_height
,
620 pattern_width
* 2, pattern_height
,
621 GL_COLOR_BUFFER_BIT
, GL_NEAREST
);
623 /* Draw test and reference images, and read them into memory */
624 test_renderer
.set_piglit_tolerance();
626 float *ref_image
= ref_renderer
.read_image(GL_RGBA
);
628 /* Compute the expected image from the reference image */
629 float *expected_image
=
630 compute_expected_image(ref_image
,
631 format
->base_internal_format
);
633 /* Check that the test image was correct */
634 unsigned num_components
=
635 piglit_num_components(format
->base_internal_format
);
637 piglit_compute_probe_tolerance(format
->base_internal_format
,
639 pass
= piglit_compare_images_color(0, 0, pattern_width
,
641 num_components
, tolerance
,
642 expected_image
, test_image
);
645 /* Show both the test and expected images on screen so that
646 * the user can diagnose problems. Pass image_count = 0 to
647 * display image without any offset applied to raster position.
649 glViewport(0, 0, piglit_width
, piglit_height
);
650 piglit_visualize_image(test_image
, format
->base_internal_format
,
651 pattern_width
, pattern_height
,
654 piglit_visualize_image(expected_image
,
655 format
->base_internal_format
,
656 pattern_width
, pattern_height
,
661 free(expected_image
);
664 /* Finally, if any error occurred, count that as a failure. */
665 pass
= piglit_check_gl_error(GL_NO_ERROR
) && pass
;
669 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;
674 print_usage_and_exit(char *prog_name
)
676 printf("Usage: %s <sample_arg> [test_set]\n"
677 " where <sample_arg> is one of:\n"
678 " <num_samples>: test supplied sample count\n"
679 " all_samples: test all power of 2 samples\n" , prog_name
);
680 piglit_report_result(PIGLIT_FAIL
);
685 piglit_init(int argc
, char **argv
)
687 if (argc
< 2 || argc
> 3)
688 print_usage_and_exit(argv
[0]);
690 /* First argument (required): num_samples */
692 if (streq(argv
[1], "all_samples"))
695 num_samples
= strtol(argv
[1], &endptr
, 0);
696 if (endptr
!= argv
[1] + strlen(argv
[1]))
697 print_usage_and_exit(argv
[0]);
700 /* Second argument (optional): test_set */
701 int test_set
= 0; /* Default to core */
703 test_set
= fbo_lookup_test_set(argv
[2]);
705 piglit_require_gl_version(21);
706 piglit_require_extension("GL_ARB_framebuffer_object");
707 piglit_require_extension("GL_ARB_vertex_array_object");
709 /* Skip the test if num_samples > GL_MAX_SAMPLES */
710 glGetIntegerv(GL_MAX_SAMPLES
, &max_samples
);
711 if (num_samples
> max_samples
)
712 piglit_report_result(PIGLIT_SKIP
);
714 fbo_formats_init_test_set(test_set
,
715 GL_TRUE
/* print_options */);
717 bool is_integer
= (test_sets
[test_index
].basetype
== GL_INT
);
719 test_pattern_vec4
= new ColorGradientSunburst(GL_UNSIGNED_NORMALIZED
);
720 test_pattern_vec4
->compile();
722 piglit_require_gl_version(30);
723 piglit_require_extension("GL_ARB_texture_multisample");
725 test_pattern_ivec4
= new ColorGradientSunburst(GL_INT
);
726 test_pattern_ivec4
->compile();
727 test_pattern_uvec4
= new ColorGradientSunburst(GL_UNSIGNED_INT
);
728 test_pattern_uvec4
->compile();
730 int_resolve_check
.prog
=
731 piglit_build_simple_program(int_resolve_check_vs
,
732 int_resolve_check_fs
);
733 glUseProgram(int_resolve_check
.prog
);
734 int_resolve_check
.u_resolve
=
735 glGetUniformLocation(int_resolve_check
.prog
, "resolve");
736 int_resolve_check
.u_msaa
=
737 glGetUniformLocation(int_resolve_check
.prog
, "msaa");
738 int_resolve_check
.u_samples
=
739 glGetUniformLocation(int_resolve_check
.prog
, "samples");
743 extern "C" enum piglit_result
746 piglit_result result
= PIGLIT_PASS
;
750 return fbo_formats_display(test_format
);
753 for (num_samples
= 0; num_samples
<= max_samples
; ) {
754 result
= fbo_formats_display(test_format
);
755 printf("Samples = %d, Result = %s\n", num_samples
,
756 piglit_result_to_string(result
));
758 num_samples
= num_samples
? num_samples
<< 1 : num_samples
+ 2;
760 if (result
== PIGLIT_SKIP
)
763 pass
= (result
== PIGLIT_PASS
) && pass
;
765 return pass
? PIGLIT_PASS
: PIGLIT_FAIL
;