[Piglit] [PATCH 1/5] msaa: Add files containing the shared code to test multiple draw buffers

Paul Berry stereotype441 at gmail.com
Thu Jul 12 10:24:56 PDT 2012


On 11 July 2012 16:16, Anuj Phogat <anuj.phogat at gmail.com> wrote:

> Functions defined in these files are utilized by following test cases:
> draw-buffers-alpha-to-one
> int-draw-buffers-alpha-to-one
> draw-buffers-alpha-to-coverage
> int-draw-buffers-alpha-to-coverage
>
> Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
> ---
>  .../draw-buffers-common.cpp                        |  747
> ++++++++++++++++++++
>  .../draw-buffers-common.h                          |   60 ++
>  2 files changed, 807 insertions(+), 0 deletions(-)
>  create mode 100644
> tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp
>  create mode 100644
> tests/spec/ext_framebuffer_multisample/draw-buffers-common.h
>
> diff --git
> a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp
> b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp
> new file mode 100644
> index 0000000..1ad44bd
> --- /dev/null
> +++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp
> @@ -0,0 +1,747 @@
> +/*
> + * Copyright © 2012 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> next
> + * paragraph) shall be included in all copies or substantial portions of
> the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#include "draw-buffers-common.h"
> +
> +/**
> + * \file draw-buffers-common.cpp
> + *
> + * This file provides utility functions to draw a test pattern to
> multiple draw
> + * buffers attached to a FBO with GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE}
> + * enabled / disabled.
>

It seems like a lot of the code in this patch is very similar to code that
already exists in sample-alpha-to-coverage.cpp and
sample-alpha-to-one.cpp.  How difficult would it be to adapt those existing
tests to use the common code?  (I think it would be ok to land this patch
series first, and do that refactoring later).

This looks like it's going to be a good set of tests.  I have a bunch of
small nit-picks below¸ but in general I like it.


> + *
> + * Expected color values are computed for each draw buffer based on the
> enabled
> + * GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE} flags and coverage value used to
> draw the
> + * test pattern.
> + *
> + * Reference image for each draw buffer is drawn in to right half of
> default
> + * framebuffer. It is used to verify the accuracy of test image as well
> as to
> + * visually compare the difference caused by enabling above flags.
> + *
> + * Test image is drawn with the same test pattern in multisample buffer
> with
> + * GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE} enabled. All multisample draw
> buffers
> + * are sequentially resolved by  blitting them to a single sample FBO.
> resolve_fbo
> + * is then blitted to left half of window system framebuffer with
> appropriate y
> + * offset. This produces three test images in the left half, each
> corresponds to
> + * a color attachment.
> + *
> + * Test image is verified by comparing it with the corresponding reference
> + * image in the right half
> + *
> + * For sample coverage and sample alpha to coverage, test image should be
> + * verified by probing the rectangles in left half of window system
> framebuffer
> + * and comparing with expected color values. OpenGL 3.0 specification
> intends to
> + * allow (but not require) the implementation to produce a dithering
> effect when
> + * the coverage value is not a strict multiple of 1 / num_samples. We
> will skip
> + * computing expected values and probing for such rectangles. They are
> drawn
> + * just to look for dithering by human inspection.
> + *
> + * Note: Testing for 3 three draw buffers is supported at present. We
> have to
>
+ * generate the fragment shader at run time to allow drawing to user
> specified
> + * number of draw buffers. I'll skip it for now as this doesn't seem to
> make
> + * any difference to test with different number of draw buffers.
>

I found this paragraph difficult to follow.  You might consider rephrasing
the first two sentences to something like this:

Note: At present, the test always uses three draw buffers.  To test other
numbers of draw buffers, we would have to modify the fragment shader in
nontrivial ways at run time.


> + *
> + * Testing of integer formats for draw buffer zero other than GL_RGBA8I
> is not
> + * supported by utility functions in this file.
> + *
> + *
> + * Author: Anuj Phogat <anuj.phogat at gmail.com>
> + */
> +
> +static Fbo ms_fbo, resolve_fbo, resolve_int_fbo;
> +static GLbitfield buffer_to_test;
> +
> +static float *coverage = NULL;
> +static float *color = NULL;
> +static float *expected = NULL;
> +
> +static int num_draw_buffers;
> +static int num_samples;
> +static int num_rects;
> +static int prog;
> +static int color_loc;
> +static int icolor_loc;
> +static int alpha_to_coverage_loc;
> +static int pattern_width;
> +static int pattern_height;
> +
> +static bool is_buffer_zero_integer_format = false;
> +
> +static const int num_components = 4; /* for RGBA formats */
> +static const int num_color_bits = 8; /* for GL_RGBA & GL_RGBA8I formats */
> +
> +static const float bg_color[4] = {
> +       0.0, 0.6, 0.0, 0.4 };
> +
> +/* Testing for three draw buffers is supported */
> +static const GLenum draw_buffers[] = {
> +       GL_COLOR_ATTACHMENT0_EXT,
> +       GL_COLOR_ATTACHMENT1_EXT,
> +       GL_COLOR_ATTACHMENT2_EXT };
> +
> +static const char *vert =
> +       "#version 130\n"
> +       "in vec2 pos;\n"
> +       "uniform float depth;\n"
> +       "void main()\n"
> +       "{\n"
> +       "  gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 0.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.
> + */
> +static const char *frag_template =
> +       "#version 130\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 icolor;\n"
>

It's kind of confusing to call this variable "icolor" because it's not
always an integer variable.  How about "frag0color" or something?


> +       "uniform vec4 color;\n"
> +       "uniform bool alphatocoverage;\n"
> +       "void main()\n"
> +       "{\n"
> +       "  frag_out_0 = icolor;\n"
> +       "  if(alphatocoverage) {\n"
> +       "    frag_out_1 = vec4(color.rgb, color.a / 2);\n"
> +       "    frag_out_2 = vec4(color.rgb, color.a / 4);\n"
> +       "  }\n"
> +       "  else {\n"
> +       "    frag_out_1 = frag_out_2 = color;\n"
> +       "  }\n"
> +       "}\n";
> +
> +const char *
> +get_out_type_glsl(void)
> +{
> +       if(is_buffer_zero_integer_format)
> +               return "ivec4";
> +       else
> +               return "vec4";
> +}
> +void
> +shader_compile(void)
> +{
> +       /* Compile program */
> +       GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
> +
> +       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);
> +
> +       GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
>

It doesn't really matter since this is a piglit test, but we should
probably free(frag) here.


> +       prog = piglit_link_simple_program(vs, fs);
> +
> +       if (!piglit_link_check_status(prog)) {
> +               piglit_report_result(PIGLIT_FAIL);
> +       }
> +
> +       glBindFragDataLocation(prog, 0, "frag_out_0");
> +       glBindFragDataLocation(prog, 1, "frag_out_1");
> +       glBindFragDataLocation(prog, 2, "frag_out_2");
> +
> +       glBindAttribLocation(prog, 0, "pos");
> +       glEnableVertexAttribArray(0);
> +
> +       /* Linking is rquired after glBindFragDataLocation */
> +       piglit_LinkProgram(prog);
> +
> +       /* Set up uniforms */
> +       glUseProgram(prog);
> +       color_loc = glGetUniformLocation(prog, "color");
> +       icolor_loc = glGetUniformLocation(prog, "icolor");
> +       alpha_to_coverage_loc = glGetUniformLocation(prog,
> "alphatocoverage");
> +}
> +
> +void
> +allocate_data_arrays(void)
> +{
> +       /* Draw 2N + 1 rectangles for N samples, each with a unique color
> +        * and coverage value
> +        */
> +       num_rects = 2 * num_samples + 1;
> +
> +       /* Allocate data arrays based on number of samples used */
> +       color = (float *) malloc(num_rects * num_components *
> sizeof(float));
> +       coverage = (float *) malloc(num_rects * sizeof(float));
> +       expected = (float *) malloc(num_draw_buffers * num_rects *
> +                                   num_components * sizeof(float));
> +
> +       for(int i = 0; i < num_rects; i++) {
> +               unsigned rect_idx = i * num_components;
> +               for(int j = 0; j < num_components - 1; j++) {
> +                       color[rect_idx + j] =
> +                       (sin((float)(rect_idx + j)) + 1) / 2;
> +               }
> +               /* Alpha value will be directly used as coverage */
> +               if (num_samples)
> +                       color[rect_idx + 3] = i * (1.0 / (2.0 *
> num_samples));
> +               else
> +                       color[rect_idx + 3] = 1.0;
> +       }
> +}
>
+
> +void
> +free_data_arrays(void)
> +{
> +       if(color != NULL) {
> +               free(color);
> +               color = NULL;
> +       }
> +       if(coverage != NULL) {
> +               free(coverage);
> +               coverage = NULL;
> +       }
> +       if(expected != NULL) {
> +               free(expected);
> +               expected = NULL;
> +       }
> +}
>

FYI, it is safe to pass a NULL pointer to free() (it does nothing if you
do), so this could be rewritten as:

void
free_data_arrays(void)
{
  free(color);
  color = NULL;
  free(coverage);
  coverage = NULL;
  free(expected);
  expected = NULL;
}


> +
> +void
> +float_color_to_int_color(int *dst, float *src)
> +{
> +       if(!dst || !src) {
> +               printf("Null src/dst pointer\n");
> +               exit(1);
> +       }
>

This check isn't really necessary IMHO.  If src or dst is null, the loop
below will segfault, and the programmer will have no less information to
debug the problem.  (In fact, if they have core dumps enabled, they will
have even more information, since they will have a core dump).


> +
> +       float offset = 1 - pow(2, (num_color_bits - 1));
> +       float scale = -2.0 * offset;
> +
> +       for (int j = 0; j < num_rects; ++j) {
> +               for (int k = 0; k < num_components; ++k) {
> +                       dst[j * num_components + k] =
> +                       scale * src[j * num_components + k] + offset;
> +               }
> +       }
> +}
> +
> +void
> +draw_pattern(bool sample_alpha_to_coverage,
> +            bool sample_alpha_to_one,
> +            bool is_reference_image,
> +            float *float_color)
> +{
> +       glUseProgram(prog);
> +       glClearColor(bg_color[0], bg_color[1],
> +                    bg_color[2], bg_color[3]);
> +       glClear(buffer_to_test);
> +
> +       if (sample_alpha_to_coverage) {
> +               if(!is_reference_image)
> +                       glEnable (GL_SAMPLE_ALPHA_TO_COVERAGE);
> +               glUniform1i(alpha_to_coverage_loc, true);
> +       }
> +       else
> +               glUniform1i(alpha_to_coverage_loc, false);
> +
> +       if (!is_reference_image && sample_alpha_to_one)
> +               glEnable (GL_SAMPLE_ALPHA_TO_ONE);
>

I think this would read more easily if we split the code to set the uniform
from the code to set up the GL state, e.g.:

glUniform1i(alpha_to_coverage_loc, sample_alpha_to_coverage);
if (!is_reference_image) {
  if (sample_alpha_to_coverage)
    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
  if (sample_alpha_to_one)
    glEnable(GL_SAMPLE_ALPHA_TO_ONE);
}


> +
> +       unsigned indices[6] = {0, 1, 2, 0, 2, 3};
> +       int integer_color[num_rects * num_components];
> +
> +       /* For integer color buffers convert the color data to integer
> format */
> +        if(is_buffer_zero_integer_format) {
> +               float_color_to_int_color(integer_color, float_color);
> +       }
> +
> +       for (int i = 0; i < num_rects; ++i) {
> +               float vertices[4][2] = {
> +               { 0.0f, 0.0f + i * (pattern_height / num_rects) },
> +               { 0.0f, (i + 1.0f) * (pattern_height / num_rects) },
> +               { pattern_width, (i + 1.0f) * (pattern_height / num_rects)
> },
> +               { pattern_width, 0.0f + i * (pattern_height / num_rects) }
> };
> +
> +               glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,
> +                                     sizeof(vertices[0]),
> +                                     (void *) vertices);
> +
> +               glUniform4fv(color_loc, 1, (float_color + i *
> num_components));
> +               if(is_buffer_zero_integer_format) {
> +                       glUniform4iv(icolor_loc, 1,
> +                                    integer_color + i * num_components);
> +               }
> +               else {
> +                       glUniform4fv(icolor_loc, 1,
> +                                    (float_color + i * num_components));
> +               }
> +               glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,
> +                              (void *) indices);
> +       }
> +
> +       if (!is_reference_image) {
> +               if (sample_alpha_to_coverage)
> +                       glDisable (GL_SAMPLE_ALPHA_TO_COVERAGE);
> +
> +               if (sample_alpha_to_one)
> +                       glDisable (GL_SAMPLE_ALPHA_TO_ONE);
> +       }
>

Personally I would just replace this with

glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
glDisable(GL_SAMPLE_ALPHA_TO_ONE);

There's no harm, and it makes it manifestly obvious that those bits will be
disabled when the function returns.


> +}
> +
> +void
> +compute_expected(bool sample_alpha_to_coverage,
> +                bool sample_alpha_to_one,
> +                int draw_buffer_count)
> +{
> +       int i, j;
> +       unsigned buffer_idx_offset = draw_buffer_count *
> +                                    num_rects *
> +                                    num_components;
> +
> +       /* Compute the coverage value used in the test */
> +       if (num_samples &&
> +           sample_alpha_to_coverage &&
> +           !is_buffer_zero_integer_format) {
> +
> +               for (i = 0; i < num_rects; i++) {
> +                       /* Coverege value for all the draw buffers comes
> from
>

"coverage"


> +                        * the fragment alpha values of draw buffer zero
> +                        */
> +                       float frag_alpha = color[i * num_components + 3];
> +                       coverage[i] = (frag_alpha < 1.0) ? frag_alpha :
> 1.0;
> +               }
> +       }
> +       else {
> +               for (i = 0; i < num_rects; i++)
> +                       coverage[i] = 1.0;
> +       }
> +
> +       /* 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 (i = 0; i < num_rects; i++) {
> +
> +               float samples_used = coverage[i] * num_samples;
> +               /* Exepected color values are computed only for integer
>

"expected"


> +                * number of samples_used. Non-integer values may result
> +                * in dithering effect.
> +                */
> +               if(samples_used == (int) samples_used) {
> +                       int rect_idx_offset = buffer_idx_offset +
> +                                             i * num_components;
> +                       for (j = 0; j < num_components - 1 ; j++) {
> +
> +                               expected[rect_idx_offset + j] =
> +                               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];
> +                       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
> +                                * fragment shader.
> +                                */
> +                               expected[alpha_idx] =
> +                                       is_buffer_zero_integer_format ?
> +                                       frag_alpha / pow(2,
> draw_buffer_count) :
> +                                       frag_alpha;
> +                       }
> +                       else if (sample_alpha_to_coverage) {
> +                               /* Taking in account alpha values modified
> by
> +                                * fragment shader.
> +                                */
> +                               frag_alpha /= pow(2, draw_buffer_count);
> +                               if(sample_alpha_to_one) {
> +                                       expected[alpha_idx] =
> +                                       1.0 * coverage[i] +
> +                                       bg_color[3] * (1 - coverage[i]);
> +                               }
> +                               else {
> +                                       expected[alpha_idx] =
> +                                       frag_alpha * coverage[i] +
> +                                       bg_color[3] * (1 - coverage[i]);
> +                               }
> +                       }
> +                       else {
> +                               expected[alpha_idx] =
> +                                       sample_alpha_to_one ? 1.0 :
> frag_alpha;
> +                       }
> +               }
> +       }
> +}
> +
> +/* This function probes all the draw buffers blitted to downsampled FBO
> + * (resolve_fbo / resolve_int_fbo) and compare against expected color
> values.
> + */
> +bool
> +probe_framebuffer_color(void)
> +{
> +       bool result = true;
> +       int * expected_int_color = NULL;
> +       int rect_width = pattern_width;
> +       int rect_height = pattern_height / num_rects;
> +
> +       for (int i = 0; i < num_draw_buffers; i++) {
> +               bool is_integer_operation = is_buffer_zero_integer_format
> && !i;
> +
> +               if(is_integer_operation) {
> +                       glBindFramebuffer(GL_READ_FRAMEBUFFER,
> +                                         resolve_int_fbo.handle);
> +                       expected_int_color = (int*) malloc(num_rects *
> +                                                          num_components *
> +                                                          sizeof(int));
> +               }
> +               else {
> +                       glBindFramebuffer(GL_READ_FRAMEBUFFER,
> +                                         resolve_fbo.handle);
> +               }
> +
> +               for (int j = 0; j < num_rects; j++) {
> +                       float samples_used = coverage[j] * num_samples;
> +                       int rect_x = 0;
> +                       int rect_y = i * pattern_height +
> +                                    j * (pattern_height / num_rects);
> +                       int rect_idx_offset = (i * num_rects + j) *
> +                                             num_components;
> +
> +                       /* Only probe rectangles with coverage value which
> is a
> +                        * strict  multiple of 1 / num_samples.
> +                        */
> +                       if(samples_used == (int)samples_used) {
> +                               if(is_integer_operation) {
> +
> float_color_to_int_color(expected_int_color,
> +                                                                expected);
> +                                       result =
> piglit_probe_rect_rgba_int(
> +                                                rect_x,
> +                                                rect_y,
> +                                                rect_width,
> +                                                rect_height,
> +                                                expected_int_color +
> +                                                rect_idx_offset)
> +                                                && result;
> +                               }
> +                               else {
> +                                       result = piglit_probe_rect_rgba(
> +                                                rect_x,
> +                                                rect_y,
> +                                                rect_width,
> +                                                rect_height,
> +                                                expected +
> rect_idx_offset)
> +                                                && result;
> +                               }
> +                       }
> +               }
> +       }
> +       if(expected_int_color)
> +               free(expected_int_color);
> +       return result;
> +}
> +
> +/**
> + * Alpha values are visualized by blending the image with a grayscale
> + * checkerboard.
> + */
> +void
> +visualize_image(float *img, bool lhs, int draw_buffer_count)
>

This function looks almost exactly like the visualize_image() function in
formats.cpp.  Can we share this code?


> +{
> +       float *visualization = (float *) malloc(sizeof(float) * 3 *
> +                              pattern_width * pattern_height);
> +       for (int y = 0; y < pattern_height; ++y) {
> +               for (int x = 0; x < pattern_width; ++x) {
> +                       float r = 0, g = 0, b = 0, a = 1;
> +                       float *pixel =
> +                               &img[(y * pattern_width + x) *
> num_components];
> +                       r = pixel[0];
> +                       g = pixel[1];
> +                       b = pixel[2];
> +                       a = pixel[3];
> +
> +                       float checker = ((x ^ y) & 0x10) ? 0.75 : 0.25;
> +                       r = r * a + checker * (1 - a);
> +                       g = g * a + checker * (1 - a);
> +                       b = b * a + checker * (1 - a);
> +
> +                       visualization[(y * pattern_width + x) * 3] = r;
> +                       visualization[(y * pattern_width + x) * 3 + 1] = g;
> +                       visualization[(y * pattern_width + x) * 3 + 2] = b;
> +               }
> +       }
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
> +       glViewport(0, 0, pattern_width, pattern_height);
> +       glUseProgram(0);
> +       glWindowPos2f(lhs ? 0 : pattern_width,
> +                     draw_buffer_count * pattern_height);
> +       glDrawPixels(pattern_width, pattern_height, GL_RGB, GL_FLOAT,
> +                    visualization);
> +       free(visualization);
> +       free(img);
>

It seems weird for this function to free the input image as a side effect.
I'd recommend doing it in the caller.


> +}
> +
> +void
> +draw_image_to_window_system_fb(int draw_buffer_count, bool lhs)
> +{
> +       unsigned rect_x = 0;
> +       unsigned rect_y = draw_buffer_count * pattern_height;
> +       unsigned array_size = num_components * pattern_width *
> pattern_height;
> +       float *image = (float *) malloc(sizeof(float) * array_size);
> +
> +       if(is_buffer_zero_integer_format && draw_buffer_count == 0) {
> +               glBindFramebuffer(GL_READ_FRAMEBUFFER,
> resolve_int_fbo.handle);
> +               int *tmp = (int *) malloc(sizeof(int) * array_size);
> +               glReadPixels(rect_x, rect_y,
> +                            pattern_width, pattern_height,
> +                            GL_RGBA_INTEGER,
> +                            GL_INT, tmp);
> +               for (unsigned i = 0; i < array_size; ++i) {
> +                       image[i] = tmp[i];
> +               }
> +
> +               /* Convert integer color data to float color data */
> +               float color_offset = 1.0 - pow(2.0, num_color_bits - 1);
> +               float color_scale = -2.0 * color_offset;
> +
> +               for (unsigned i = 0; i < array_size; ++i) {
> +                       image[i] = (image[i] - color_offset) / color_scale;
> +               }
> +               free(tmp);
> +       }
> +       else{
> +               glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo.handle);
> +               glReadPixels(rect_x, rect_y,
> +                            pattern_width,
> +                            pattern_height,
> +                            GL_RGBA,
> +                            GL_FLOAT, image);
> +       }
> +       visualize_image(image, lhs, draw_buffer_count);
> +}
> +
> +void
> +draw_test_image(bool sample_alpha_to_coverage, bool sample_alpha_to_one)
> +{
> +       /* Draw test pattern in multisample ms_fbo with
> +        * GL_SAMPLE_ALPHA_TO_COVERAGE enabled
> +        */
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
> +       glDrawBuffers(num_draw_buffers, draw_buffers);
> +       ms_fbo.set_viewport();
> +
> +       draw_pattern(sample_alpha_to_coverage,
> +                    sample_alpha_to_one,
> +                    false /* is_reference_image */,
> +                    color);
> +
> +       for(int i = 0; i < num_draw_buffers; i++) {
> +
> +               /* Blit ms_fbo to singlesample FBO to resolve multisample
> +                * buffer.
> +                */
> +               glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);
> +               glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i);
> +
> +               if ( is_buffer_zero_integer_format && !i)
> +                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> +                                         resolve_int_fbo.handle);
> +               else
> +                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> +                                         resolve_fbo.handle);
> +
> +               /* Blit all the draw buffers to resolve_fbo /
> resolve_int_fbo
> +                * with different y_offset.
> +                */
> +               unsigned y_offset = i * pattern_height;
> +               glBlitFramebuffer(0, 0,
> +                                 pattern_width, pattern_height,
> +                                 0, y_offset,
> +                                 pattern_width, pattern_height + y_offset,
> +                                 buffer_to_test, GL_NEAREST);
> +
> +               draw_image_to_window_system_fb(i /* draw_buffer_count */,
> +                                              true /* lhs */);
> +
> +               /* Expected color values for all the draw buffers are
> computed
> +                * to aid probe_framebuffer_color() in verification.
> +                */
> +               if(sample_alpha_to_coverage) {
> +                       /* Expected color is different for different draw
> +                        * buffers
> +                        */
> +                       compute_expected(sample_alpha_to_coverage,
> +                                        sample_alpha_to_one,
> +                                        i /* draw_buffer_count */);
> +               }
> +       }
> +}
> +
> +void
> +draw_reference_image(bool sample_alpha_to_coverage, bool
> sample_alpha_to_one)
> +{
> +       /* Draw test pattern in multisample ms_fbo with
> +        * GL_SAMPLE_ALPHA_TO_COVERAGE disabled.
> +        */
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
> +       glDrawBuffers(num_draw_buffers, draw_buffers);
> +       ms_fbo.set_viewport();
> +
> +       if(sample_alpha_to_coverage) {
> +               draw_pattern(sample_alpha_to_coverage,
> +                            sample_alpha_to_one,
> +                            true /* is_reference_image */,
> +                            color);
> +       }
> +       else {
> +               /* Value of draw_buffer_count doesn't matter in this case
> */
> +               compute_expected(sample_alpha_to_coverage,
> +                                sample_alpha_to_one,
> +                                0 /* draw_buffer_count */);
> +               draw_pattern(sample_alpha_to_coverage,
> +                            sample_alpha_to_one,
> +                            true /* is_reference_image */,
> +                            expected);
> +       }
> +
> +       for(int i = 0; i < num_draw_buffers; i++) {
> +
> +               /* Blit ms_fbo to resolve_fbo to resolve multisample
> buffer */
> +               glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);
> +               glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i);
> +               if (is_buffer_zero_integer_format && !i) {
> +                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> +                                         resolve_int_fbo.handle);
> +               }
> +               else {
> +                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
> +                                         resolve_fbo.handle);
> +               }
> +
> +               /* Blit all the draw buffers to resolve_fbo with different
> +                * y_offset.
> +                */
> +               unsigned y_offset = i * pattern_height;
> +               glBlitFramebuffer(0, 0,
> +                                 pattern_width, pattern_height,
> +                                 0, y_offset,
> +                                 pattern_width, pattern_height + y_offset,
> +                                 buffer_to_test, GL_NEAREST);
> +
> +               draw_image_to_window_system_fb(i /* buffer_count */,
> +                                              false  /* lhs */ );
> +       }
> +}
> +
> +void
> +ms_fbo_and_draw_buffers_setup(int samples,
> +                             int width,
> +                             int height,
> +                             int n_attachments,
> +                             GLenum buffer_zero_format)
> +{
> +       int maxBuffers;
> +       glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxBuffers);
> +
> +       /* Ensure that requested number of color attachments are
> +        * supported by the implementation and fragment shader.
> +        */
> +       if (n_attachments <= (int) ARRAY_SIZE(draw_buffers) &&
> +           n_attachments <= maxBuffers)
> +               num_draw_buffers = n_attachments;
> +       else
> +               printf("Number of attachments requested are not
> supported\n");
>

In the else block, we should probably add
"piglit_report_result(PIGLIT_SKIP);" so that the test just skips on
implementations that don't support enough attachment points.


> +
> +       pattern_width = width;
> +       pattern_height = height;
> +
> +       /* Setup frame buffer objects with required configuration */
> +       FboConfig ms_config(samples, pattern_width, pattern_height);
> +       ms_config.color_internalformat = buffer_zero_format;
> +       ms_fbo.setup(ms_config);
> +
> +       /* Create resolve_fbo with dimensions large enough to accomodate
> +        * all the draw buffers
> +        */
> +       FboConfig resolve_config(0, pattern_width,
> +                                num_draw_buffers * pattern_height);
> +       resolve_config.color_internalformat = GL_RGBA;
> +       resolve_fbo.setup(resolve_config);
> +
> +       /* Create resolve_int_fbo to store downsampled integer draw buffer
> */
> +       if (buffer_zero_format == GL_RGBA8I) {
> +               resolve_config.color_internalformat = GL_RGBA8I;
> +               /* Assuming single integer buffer */
> +               resolve_config.height = pattern_height;
> +               resolve_int_fbo.setup(resolve_config);
> +               is_buffer_zero_integer_format = true;
> +       }
> +       else if (buffer_zero_format != GL_RGBA){
> +               printf("Draw buffer zero format is not"
> +                      " supported by test functions.\n");
> +               piglit_report_result(PIGLIT_SKIP);
>

This should only happen if there is a bug in the piglit test, right?
(because the caller passed an unexpected value to
ms_fbo_and_draw_buffers_setup())  In that case, this should be PIGLIT_FAIL
so that we notice the problem and fix it.  PIGLIT_SKIP should just be for
situations where the test is inapplicable because the underlying GL
implementation is missing a required extension (or something similar).


> +       }
> +
> +        if (!piglit_check_gl_error(GL_NO_ERROR)) {
> +               printf("Error setting up frame buffer objects\n");
> +               piglit_report_result(PIGLIT_FAIL);
> +        }
> +
> +       /* Query the number of samples used in ms_fbo. OpenGL
> implementation
> +        * may create FBO with more samples per pixel than what is
> requested.
> +        */
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
> +       glGetIntegerv(GL_SAMPLES, &num_samples);
> +
> +       /* Attach additional color buffers to multisample FBO with default
> +        * non-integer format (GL_RGBA.)
> +        */
> +       GLuint color_rb[num_draw_buffers - 1];
> +       glGenRenderbuffers(num_draw_buffers - 1, color_rb);
> +
> +       for(int i = 0; i < num_draw_buffers - 1; i++) {
> +               glBindRenderbuffer(GL_RENDERBUFFER, color_rb[i]);
> +               glRenderbufferStorageMultisample(GL_RENDERBUFFER,
> +                                       ms_fbo.config.num_samples,
> +                                       GL_RGBA,
> +                                       ms_fbo.config.width,
> +                                       ms_fbo.config.height);
> +
> +               glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
> +                                         GL_COLOR_ATTACHMENT0 + (i + 1),
> +                                         GL_RENDERBUFFER,
> +                                         color_rb[i]);
> +       }
> +
> +       GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
> +        if (status != GL_FRAMEBUFFER_COMPLETE) {
> +               printf("Error attaching additional color buffers\n");
> +               piglit_report_result(PIGLIT_FAIL);
> +       }
> +       buffer_to_test = GL_COLOR_BUFFER_BIT;
> +}
> diff --git a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h
> b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h
> new file mode 100644
> index 0000000..7e6972c
> --- /dev/null
> +++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h
> @@ -0,0 +1,60 @@
> +/* Copyright © 2012 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the
> "Software"),
> + * to deal in the Software without restriction, including without
> limitation
> + * the rights to use, copy, modify, merge, publish, distribute,
> sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the
> next
> + * paragraph) shall be included in all copies or substantial portions of
> the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
> EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT
> SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
> OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> DEALINGS
> + * IN THE SOFTWARE.
> + */
> +
> +#include "common.h"
> +
> +/**
> + * \file draw-buffers-common.h
> + * This file declares common functions which are used by multiple draw
> buffer
> + * test cases.
> + */
> +
> +/* Allocates all the relevant data arrays required in the test */
> +void allocate_data_arrays(void);
> +
> +/* Draws a test pattern without sample_alpha_to_coverage and
> + * sample_alpha_to_one
> + */
> +void draw_reference_image(bool sample_alpha_to_coverage,
> +                         bool sample_alpha_to_one);
> +
> +/* Draws the test pattern with either sample_alpha_to_coverage or
> + * sample_alpha_to_one enabled
> + */
> +void draw_test_image(bool sample_alpha_to_coverage,
> +                    bool sample_alpha_to_one);
> +
> +/* Frees the previously allocated data arrays */
> +void free_data_arrays(void);
> +
> +/* Initilaizes multisample framebuffer object with multiple draw buffers
> */
> +void ms_fbo_and_draw_buffers_setup(int samples,
> +                                  int width, int height,
> +                                  int n_attachments,
> +                                  GLenum buffer_zero_format);
> +
> +/* Probe downsampled FBO (resolve_fbo / resolve_int_fbo) to compare
> against
> + * expected color for each draw buffer
> + */
> +bool probe_framebuffer_color(void);
> +
> +void shader_compile(void);
> --
> 1.7.7.6
>
> _______________________________________________
> Piglit mailing list
> Piglit at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/piglit
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/piglit/attachments/20120712/d084a3bc/attachment-0001.html>


More information about the Piglit mailing list