From 48163232ae5978276a89c90bc1f1b36a3c1d39c4 Mon Sep 17 00:00:00 2001 From: Anuj Phogat Date: Wed, 25 Jul 2012 13:39:11 -0700 Subject: [PATCH] msaa: Make changes in shared code to accomodate dual-src-blending test cases These changes are required to enable dual-src-blending test cases to use the shared code: Generate fragment shader which outputs relevant color values. Modify compute_expected_color() function to support dual-src-blending. V2: Removed unnecessary blitting code in case of dual-src-blending. Also set src1_alpha to 1.0 when sample-alpha-to-one is enabled. Signed-off-by: Anuj Phogat Reviewed-by: Paul Berry --- .../alpha-to-coverage-no-draw-buffer-zero.cpp | 3 +- .../alpha-to-one-msaa-disabled.cpp | 3 +- .../alpha-to-one-single-sample-buffer.cpp | 3 +- .../draw-buffers-alpha-to-coverage.cpp | 3 +- .../draw-buffers-alpha-to-one.cpp | 3 +- .../draw-buffers-common.cpp | 168 ++++++++++++++---- .../draw-buffers-common.h | 2 +- .../int-draw-buffers-alpha-to-coverage.cpp | 3 +- .../int-draw-buffers-alpha-to-one.cpp | 3 +- .../sample-alpha-to-coverage.cpp | 5 +- .../sample-alpha-to-one.cpp | 3 +- 11 files changed, 156 insertions(+), 43 deletions(-) diff --git a/tests/spec/ext_framebuffer_multisample/alpha-to-coverage-no-draw-buffer-zero.cpp b/tests/spec/ext_framebuffer_multisample/alpha-to-coverage-no-draw-buffer-zero.cpp index ef6077878..18ac8ebcb 100644 --- a/tests/spec/ext_framebuffer_multisample/alpha-to-coverage-no-draw-buffer-zero.cpp +++ b/tests/spec/ext_framebuffer_multisample/alpha-to-coverage-no-draw-buffer-zero.cpp @@ -97,7 +97,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_NONE /* color_buffer_zero_format */); - shader_compile(); + shader_compile(true /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/alpha-to-one-msaa-disabled.cpp b/tests/spec/ext_framebuffer_multisample/alpha-to-one-msaa-disabled.cpp index 2ad09fd73..c0e1ea75c 100644 --- a/tests/spec/ext_framebuffer_multisample/alpha-to-one-msaa-disabled.cpp +++ b/tests/spec/ext_framebuffer_multisample/alpha-to-one-msaa-disabled.cpp @@ -87,7 +87,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_RGBA); - shader_compile(); + shader_compile(false /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/alpha-to-one-single-sample-buffer.cpp b/tests/spec/ext_framebuffer_multisample/alpha-to-one-single-sample-buffer.cpp index 6bc390ae1..4f58e027b 100644 --- a/tests/spec/ext_framebuffer_multisample/alpha-to-one-single-sample-buffer.cpp +++ b/tests/spec/ext_framebuffer_multisample/alpha-to-one-single-sample-buffer.cpp @@ -65,7 +65,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_RGBA); - shader_compile(); + shader_compile(false /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-coverage.cpp b/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-coverage.cpp index 20a69bc62..31213f616 100644 --- a/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-coverage.cpp +++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-coverage.cpp @@ -95,7 +95,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_RGBA); - shader_compile(); + shader_compile(true /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-one.cpp b/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-one.cpp index 66bfd1c55..53127aa28 100644 --- a/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-one.cpp +++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-alpha-to-one.cpp @@ -116,7 +116,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_RGBA); - shader_compile(); + shader_compile(false /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp index 88765689a..1a898b2ba 100644 --- a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp +++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp @@ -88,6 +88,7 @@ static int pattern_width; static int pattern_height; static bool is_buffer_zero_integer_format = false; +static bool is_dual_src_blending = false; static GLenum draw_buffer_zero_format; static const int num_components = 4; /* for RGBA formats */ @@ -116,30 +117,31 @@ static const char *vert = " gl_Position = vec4(eye_pos.xy, 2 * depth - 1.0, 1.0);\n" "}\n"; -/* Fragment shader outputs to three draw buffers. Output different alpha values - * to different draw buffers. This is required to verify that alpha values from - * draw buffer zero are used to determine the fragment coverage value for all - * the draw buffers. +/* Fragment shader generates three different color outputs. Different color + * values are generated based on if sample_alpha_to_coverage / dual_src_blend + * are enabled or not. */ static const char *frag_template = "#version 130\n" + "#define DUAL_SRC_BLEND %d\n" + "#define ALPHA_TO_COVERAGE %d\n" "#define OUT_TYPE %s\n" "out OUT_TYPE frag_out_0;\n" "out vec4 frag_out_1;\n" "out vec4 frag_out_2;\n" "uniform OUT_TYPE frag_0_color;\n" "uniform vec4 color;\n" - "uniform bool alphatocoverage;\n" "void main()\n" "{\n" " frag_out_0 = frag_0_color;\n" - " if(alphatocoverage) {\n" + " #if DUAL_SRC_BLEND\n" + " frag_out_1 = vec4(color.rgb, 1.0 - color.a / 2.0);\n" + " #elif ALPHA_TO_COVERAGE\n" " frag_out_1 = vec4(color.rgb, color.a / 2);\n" " frag_out_2 = vec4(color.rgb, color.a / 4);\n" - " }\n" - " else {\n" + " #else\n" " frag_out_1 = frag_out_2 = color;\n" - " }\n" + " #endif\n" "}\n"; const char * @@ -151,16 +153,19 @@ get_out_type_glsl(void) return "vec4"; } void -shader_compile(void) +shader_compile(bool sample_alpha_to_coverage, bool dual_src_blend) { + is_dual_src_blending = dual_src_blend; /* Compile program */ GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert); + /* Generate appropriate fragment shader program */ const char *out_type_glsl = get_out_type_glsl();; unsigned frag_alloc_len = strlen(frag_template) + strlen(out_type_glsl) + 1; char *frag = (char *) malloc(frag_alloc_len); - sprintf(frag, frag_template, out_type_glsl); + sprintf(frag, frag_template, is_dual_src_blending, + sample_alpha_to_coverage, out_type_glsl); GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag); prog = piglit_link_simple_program(vs, fs); @@ -170,12 +175,18 @@ shader_compile(void) } free(frag); - glBindFragDataLocation(prog, 0, "frag_out_0"); - /* For multiple draw buffers */ - if (num_draw_buffers > 1) { + if (is_dual_src_blending) { + glBindFragDataLocationIndexed(prog, 0, 0, "frag_out_0"); + glBindFragDataLocationIndexed(prog, 0, 1, "frag_out_1"); + + } + else if (num_draw_buffers > 1) { + glBindFragDataLocation(prog, 0, "frag_out_0"); glBindFragDataLocation(prog, 1, "frag_out_1"); glBindFragDataLocation(prog, 2, "frag_out_2"); } + else + glBindFragDataLocation(prog, 0, "frag_out_0"); glBindAttribLocation(prog, 0, "pos"); glEnableVertexAttribArray(0); @@ -331,6 +342,76 @@ draw_pattern(bool sample_alpha_to_coverage, free(integer_color); } +float +get_alpha_blend_factor(float src0_alpha, float src1_alpha, + bool compute_src) +{ + GLint blend_func; + if(compute_src) + glGetIntegerv(GL_BLEND_SRC_RGB, &blend_func); + else + glGetIntegerv(GL_BLEND_DST_RGB, &blend_func); + + switch(blend_func) { + case GL_SRC_ALPHA: + return src0_alpha; + break; + case GL_ONE_MINUS_SRC_ALPHA: + return (1.0 - src0_alpha); + break; + case GL_SRC1_ALPHA: + return src1_alpha; + break; + case GL_ONE_MINUS_SRC1_ALPHA: + return (1.0 - src1_alpha); + break; + default: + printf("Blend function is not supported" + " by test case\n"); + } + return -1; +} + +void +compute_blend_color(float *frag_color, int rect_count, + bool sample_alpha_to_one) +{ + float src_blend_factor, dst_blend_factor; + /* Taking in to account alpha values output by + * fragment shader. + */ + float src0_alpha = color[rect_count * num_components + 3]; + float src1_alpha = 1.0 - src0_alpha / 2.0; + + if(sample_alpha_to_one && num_samples) { + /* Set fragment src0_alpha, src1_alpha to 1.0 and use them + * to compute blending factors. + */ + src0_alpha = 1.0; + src1_alpha = 1.0; + } + + src_blend_factor = get_alpha_blend_factor(src0_alpha, + src1_alpha, + true); + dst_blend_factor = get_alpha_blend_factor(src0_alpha, + src1_alpha, + false); + /* Using default BlendEquation, blend_color is: + * src0_color * src_blend_factor + dst_color * dst_blend_factor + */ + for (int j = 0; j < num_components; j++) { + float blend_color= + color[rect_count * num_components + j] * + src_blend_factor + + bg_color[j] * + dst_blend_factor; + + frag_color[rect_count * num_components + j] = + (blend_color > 1) ? 1.0 : blend_color; + } +} + void compute_expected_color(bool sample_alpha_to_coverage, bool sample_alpha_to_one, @@ -339,18 +420,9 @@ compute_expected_color(bool sample_alpha_to_coverage, unsigned buffer_idx_offset = draw_buffer_count * num_rects * num_components; - /* Coverage value decides the number of samples in multisample buffer - * covered by an incoming fragment, which will then receive the - * fragment data. When the multisample buffer is resolved it gets - * blended with the background color which is written to the remaining - * samples. - * Page 254 (page 270 of the PDF) of the OpenGL 3.0 spec says: - * "The method of combination is not specified, though a simple average - * computed independently for each color component is recommended." - * This is followed by NVIDIA and AMD in their proprietary drivers. - */ for (int i = 0; i < num_rects; i++) { + float *frag_color = NULL; float samples_used = coverage[i] * num_samples; /* Expected color values are computed only for integer * number of samples_used. Non-integer values may result @@ -359,21 +431,49 @@ compute_expected_color(bool sample_alpha_to_coverage, if(samples_used == (int) samples_used) { int rect_idx_offset = buffer_idx_offset + i * num_components; + frag_color = (float *) malloc(num_rects * + num_components * + sizeof(float)); + + /* Do dual source blending computations */ + if(is_dual_src_blending) { + compute_blend_color(frag_color, + i /* rect_count */, + sample_alpha_to_one); + } + else { + memcpy(frag_color, color, + num_rects * num_components * + sizeof(float)); + } + + /* Coverage value decides the number of samples in + * multisample buffer covered by an incoming fragment, + * which will then receive the fragment data. When the + * multisample buffer is resolved it gets blended with + * the background color which is written to the + * remaining samples. Page 254 (page 270 of the PDF) of + * the OpenGL 3.0 spec says: "The method of combination + * is not specified, though a simple average computed + * independently for each color component is recommended." + * This is followed by NVIDIA and AMD in their proprietary + * linux drivers. + */ for (int j = 0; j < num_components - 1 ; j++) { expected_color[rect_idx_offset + j] = - color[i * num_components + j] * coverage[i] + + frag_color[i * num_components + j] * coverage[i] + bg_color[j] * (1 - coverage[i]); } /* Compute expected alpha values of draw buffers */ - float frag_alpha = color[i * num_components + 3]; + float frag_alpha = frag_color[i * num_components + 3]; int alpha_idx = rect_idx_offset + 3; if ((!num_samples && !sample_alpha_to_coverage) || is_buffer_zero_integer_format) { - /* Taking in account alpha values modified by + /* Taking in to account alpha values output by * fragment shader. */ expected_color[alpha_idx] = @@ -382,7 +482,7 @@ compute_expected_color(bool sample_alpha_to_coverage, frag_alpha; } else if (sample_alpha_to_coverage) { - /* Taking in account alpha values modified by + /* Taking in to account alpha values output by * fragment shader. */ frag_alpha /= (1 << draw_buffer_count); @@ -402,6 +502,7 @@ compute_expected_color(bool sample_alpha_to_coverage, sample_alpha_to_one ? 1.0 : frag_alpha; } } + free(frag_color); } } @@ -645,15 +746,16 @@ draw_test_image(bool sample_alpha_to_coverage, bool sample_alpha_to_one) pattern_width, pattern_height + y_offset, buffer_to_test, GL_NEAREST); - if(buffer_to_test == GL_COLOR_BUFFER_BIT) + if(buffer_to_test == GL_COLOR_BUFFER_BIT) { draw_image_to_window_system_fb(i /* draw_buffer_count */, false /* rhs */); + } /* Expected color values for all the draw buffers are computed * to aid probe_framebuffer_color() and probe_framebuffer_depth() * in verification. */ - if(sample_alpha_to_coverage) { + if(sample_alpha_to_coverage || is_dual_src_blending) { /* Expected color is different for different draw * buffers */ @@ -716,8 +818,10 @@ draw_reference_image(bool sample_alpha_to_coverage, bool sample_alpha_to_one) pattern_width, pattern_height + y_offset, buffer_to_test, GL_NEAREST); - draw_image_to_window_system_fb(i /* buffer_count */, - true /* rhs */ ); + if(buffer_to_test == GL_COLOR_BUFFER_BIT) { + draw_image_to_window_system_fb(i /* draw_buffer_count */, + true /* rhs */); + } } } diff --git a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h index b36bed3c6..43a8e42b7 100644 --- a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h +++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h @@ -63,4 +63,4 @@ bool probe_framebuffer_color(void); */ bool probe_framebuffer_depth(void); -void shader_compile(void); +void shader_compile(bool sample_alpha_to_coverage, bool dual_src_blend); diff --git a/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-coverage.cpp b/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-coverage.cpp index 40b9ddfb1..cfd90e559 100644 --- a/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-coverage.cpp +++ b/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-coverage.cpp @@ -96,7 +96,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_RGBA8I); - shader_compile(); + shader_compile(true /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-one.cpp b/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-one.cpp index 7dae6bf3a..9827db8f4 100644 --- a/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-one.cpp +++ b/tests/spec/ext_framebuffer_multisample/int-draw-buffers-alpha-to-one.cpp @@ -93,7 +93,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_RGBA8I); - shader_compile(); + shader_compile(false /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/sample-alpha-to-coverage.cpp b/tests/spec/ext_framebuffer_multisample/sample-alpha-to-coverage.cpp index 0559adc3b..38e4ae9e5 100644 --- a/tests/spec/ext_framebuffer_multisample/sample-alpha-to-coverage.cpp +++ b/tests/spec/ext_framebuffer_multisample/sample-alpha-to-coverage.cpp @@ -28,7 +28,7 @@ * * Verify sample alpha to coverage with multisample FBO * - * When rendering to multiple draw buffers, fragment's alpha value should be + * When rendering to multisample FBO, fragment's alpha value should be * used to determine the coverage value. * * This test operates by drawing a pattern in multisample FBO to generate @@ -103,7 +103,8 @@ piglit_init(int argc, char **argv) num_attachments, buffer_to_test, GL_RGBA); - shader_compile(); + shader_compile(true /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result diff --git a/tests/spec/ext_framebuffer_multisample/sample-alpha-to-one.cpp b/tests/spec/ext_framebuffer_multisample/sample-alpha-to-one.cpp index 76d056feb..85a08d5fa 100644 --- a/tests/spec/ext_framebuffer_multisample/sample-alpha-to-one.cpp +++ b/tests/spec/ext_framebuffer_multisample/sample-alpha-to-one.cpp @@ -87,7 +87,8 @@ piglit_init(int argc, char **argv) num_attachments, GL_COLOR_BUFFER_BIT, GL_RGBA); - shader_compile(); + shader_compile(false /* sample_alpha_to_coverage */, + false /* dual_src_blend */); } enum piglit_result