[Piglit] [PATCH 2/4] Add test to verify glSampleCoverage with multisample fbo

Paul Berry stereotype441 at gmail.com
Sat Jun 16 07:54:04 PDT 2012


On 8 June 2012 14:43, Anuj Phogat <anuj.phogat at gmail.com> wrote:

> This test varifies that the coverage value set by glSampleCoverage()
> decides
> the number of samples in multisample buffer covered by an incoming
> fragment,
> which will receive the fragment data.
>

This test seems to assume that the coverage specified by glSampleCoverage()
will be applied exactly, and uniformly, to each pixel.  In other words, if
the coverage value is 0.25, then exactly 25% of the samples for each pixel
will be covered.  There are two problems with this assumption.  First,
there's no guarantee that the coverage value will map to an integer number
of samples (for example, if the coverage value is 0.25 but the FBO has an
oversampling factor of 2, that would mean that 0.5 samples per pixel should
be covered).  Second, the GL 3.0 spec does not require the implementation
to apply the coverage uniformly.  In fact, it encourages the implementation
not to.  On p243, the GL 3.0 spec says:

"No specific algorithm is required for converting the sample alpha values
to a temporary coverage value. It is intended that the number of 1’s in the
temporary coverage be proportional to the set of alpha values for the
fragment, with all 1’s corresponding to the maximum of all alpha values,
and all 0’s corresponding to all alpha values being 0. The alpha values
used to generate a coverage value are clamped to the range [0, 1]. It is
also intended that the algorithm be pseudo-random in nature, to avoid image
artifacts due to regular coverage sample locations. The algorithm can and
probably should be different at different pixel locations. If it does
differ, it should be defined relative to window, not screen, coordinates,
so that rendering results are invariant with respect to window position."

It seems clear that the spec writers intended 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.  Since no one has, to my knowledge,
implemented glSampleCoverage() in Mesa yet, it would be nice if we could
use this test to see if other implementations do this kind of dithering or
not.  (FWIW I *think* that my nVidia reference system doesn't do any
dithering)  If the implementation does a dithering effect, then the
coverage values you use in this test (0, 0.25, 0.75, and 1.0) will only
show dithering when oversampling by a factor that is not a multiple of 4
(e.g. 2x oversampling).  It would be nice if we could observe the presence
or absence of dithering at all multisampling factors.

Also, your compute_expected() function seems to assume that no dithering
occurs, and that coverage produces perfect blending for all multisampling
factors.  This means that it fails with 2x oversampling on my nVidia system.

Here's a possible way that we could modify the test so that we could see
dithering behaviour if it's present: instead of drawing 4 rectangles, draw
2*N+1 of them (where N is the number of samples per pixel in the
framebuffer).  Let the coverage value in each of these rectangles be i/2N,
so for example if N=4, then the coverage values would be 0.0, 0.125, 0.25,
0.375, 0.5, 0.625, 0.75, 0.825, 1.0.  N+1 of the rectangles have coverage
values that result in an integer number of samples (0.0, 0.25, 0.5, 0.75,
and 1.0 in this case)--have the test verify that those rectangles get the
exact expected color.  The other N rectangles (0.125, 0.375, 0.625, 0.825)
are just for human inspection so that we can look for dithering.

Note: if you decide to try this suggestion, make sure that you determine
the value for N by calling
glGetRenderbufferParameteriv(GL_RENDERBUFFER_SAMPLES), because it's
possible that the implementation will give you a framebuffer with more
samples/pixel than you requested.


>
> V2: Add the testing for glSampleCoverage() with coverage mask invert
> enabled
>    / disabled. Resolve the multisample FBO to a single sample FBO in place
>    of doing it on window system framebuffer. This fixes the color buffer
>    failures on NVIDIA due to sRGB.
>
> Note: This test fails for depth buffer on AMD and NVIDIA. Depth buffer is
> not
>      modified even if the incoming multisample fragment passes the depth
> test
>      and has a coverage = 1.0.
>

The reason this test is failing on nVidia is because you're making an
assumption about how MSAA depth buffers work that isn't true.  You're
assuming that when a depth buffer is resolved, depth values from each
sample get averaged together, just like in a color buffer.  What really
happens is that a single depth value is chosen (probably the depth value
from sample #0).

If you want to test that glSampleCoverage works properly with depth
buffers, then after drawing into the depth buffer, you'll have to do a
drawing operation that causes a change to the color buffer based on the
contents of the depth buffer.  For example, you could do this:

1. Clear the depth buffer to a far depth value.
2. Clear the color buffer to black.
3. Enable GL_SAMPLE_COVERAGE.
4. Draw a rectangle having a near depth value.  This should cause some of
each pixel's samples to attain the near depth value, and some to remain at
the far depth value.
5. Disable GL_SAMPLE_COVERAGE.
6. Draw a white rectangle at an intermediate depth value.  This will cause
all samples that have the far depth value to be painted white, and all
samples that have the near depth value to stay black.
7. Blit the color buffer to a single-sampled FBO.  This should cause the
white and black samples of each pixel to mix, forming gray.
8. Verify that the appropriate shade of gray was produced.

However, having said all that, I'm not certain it's necessary.  The point
in the graphics pipeline where glSampleCoverage() takes effect is the point
where the pipeline determines which samples are covered by the primitive.
That's before the point where the output of the fragment shader is split
into the various buffers.  So I think it's very likely that if
glSampleCoverage() works properly for color buffers, it will work properly
for depth buffers too.  I would be content to just remove the depth buffer
part of this test.

If would rather be on the safe side and test the depth buffer as well, then
I would encourage you to think about whether it's necessary to test the
stencil buffer as well.


>
> Signed-off-by: Anuj Phogat <anuj.phogat at gmail.com>
> ---
>  tests/all.tests                                    |    7 +
>  .../ext_framebuffer_multisample/CMakeLists.gl.txt  |    1 +
>  .../sample-coverage.cpp                            |  376
> ++++++++++++++++++++
>  3 files changed, 384 insertions(+), 0 deletions(-)
>  create mode 100644
> tests/spec/ext_framebuffer_multisample/sample-coverage.cpp
>
> diff --git a/tests/all.tests b/tests/all.tests
> index 463e927..a52b745 100644
> --- a/tests/all.tests
> +++ b/tests/all.tests
> @@ -1386,6 +1386,13 @@ for num_samples in (2, 4, 8, 16, 32):
>                 test_name)
>         ext_framebuffer_multisample[test_name] = PlainExecTest(executable)
>
> +for num_samples in (2, 4, 8, 16, 32):
> +        for buffer_type in ('color', 'depth'):
> +                test_name = ' '.join(['sample-coverage',
> str(num_samples), buffer_type])
> +                executable = 'ext_framebuffer_multisample-{0}
> -auto'.format(
> +                        test_name)
> +                ext_framebuffer_multisample[test_name] =
> PlainExecTest(executable)
> +
>  ext_framebuffer_object = Group()
>  spec['EXT_framebuffer_object'] = ext_framebuffer_object
>  add_fbo_stencil_tests(ext_framebuffer_object, 'GL_STENCIL_INDEX1')
> diff --git a/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> b/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> index e18f410..17a9571 100644
> --- a/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> +++ b/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt
> @@ -26,6 +26,7 @@ piglit_add_executable
> (ext_framebuffer_multisample-polygon-smooth common.cpp pol
>  piglit_add_executable (ext_framebuffer_multisample-renderbuffer-samples
> renderbuffer-samples.c)
>  piglit_add_executable
> (ext_framebuffer_multisample-renderbufferstorage-samples
> renderbufferstorage-samples.c)
>  piglit_add_executable (ext_framebuffer_multisample-samples samples.c)
> +piglit_add_executable (ext_framebuffer_multisample-sample-coverage
> common.cpp sample-coverage.cpp)
>  piglit_add_executable (ext_framebuffer_multisample-turn-on-off common.cpp
> turn-on-off.cpp)
>  piglit_add_executable (ext_framebuffer_multisample-unaligned-blit
> common.cpp unaligned-blit.cpp)
>  piglit_add_executable (ext_framebuffer_multisample-upsample common.cpp
> upsample.cpp)
> diff --git a/tests/spec/ext_framebuffer_multisample/sample-coverage.cpp
> b/tests/spec/ext_framebuffer_multisample/sample-coverage.cpp
> new file mode 100644
> index 0000000..fedda72
> --- /dev/null
> +++ b/tests/spec/ext_framebuffer_multisample/sample-coverage.cpp
> @@ -0,0 +1,376 @@
> +/*
> + * 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 sample-coverage.cpp
> + *
> + * Verify glSampleCoverage() with and without coverage mask invert
> + *
> + * This test operates by drawing test pattern in a multisample FBO with
> + * GL_SAMPLE_COVERAGE disabled.
> + *
> + * Blit the multisample_fbo to right half of window system framebuffer.
> + * This is used as reference image to see the visual difference caused by
> + * the sample coverage value.
> + *
> + * Compute the expected color values based on the coverage value used to
> + * draw the test pattern.
> + *
> + * Clear the multisample framebuffer to a unique color/depth. Draw the
> + * same test pattern for the second time in multisample buffer with
> + * GL_SAMPLE_COVERAGE enabled. Resolve the multisample FBO by  blitting
> + * it to a single sample FBO. Blit the resolve_fbo to left half of window
> + * system framebuffer. This is the test image.
> + *
> + * Probe the left half of window syetem framebuffer and compare with
> + * expected color values.
> + *
> + * Repeat the above testing with coverage mask invert as well.
> + *
> + * Author: Anuj Phogat <anuj.phogat at gmail.com>
> + */
> +
> +int piglit_width = 512; int piglit_height = 256;
> +int piglit_window_mode =
> +       GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA | GLUT_DEPTH;
> +const int pattern_width = 256; const int pattern_height = 256;
> +
> +static Fbo ms_fbo, resolve_fbo;
> +static GLint num_samples;
> +static float expected[4][4];
> +static GLbitfield buffer_to_test;
> +
> +static const float bg_depth = 0.80;
> +static const float bg_color[4] =
> +       {0.0, 0.0, 1.0, 0.8};
> +
> +static const float depth[4] =
> +       {0.0, 0.25, 0.60, 0.70};
> +
> +static const float cov[4] =
> +       {0.0, 0.25, 0.75, 1.0};
>
+
> +static const float color[4][4] = {
> +       /* Red */
> +       {1.0, 0.0, 0.0, 1.0},
> +       /* Green */
> +       {0.0, 1.0, 0.0, 0.50},
> +       /* Yellow */
> +       {1.0, 1.0, 0.0, 0.75},
> +       /* Cyan */
> +       {0.0, 1.0, 1.0, 0.45} };
> +
> +static GLint prog;
> +static GLint color_loc;
> +static GLint depth_loc;
> +
> +static const char *vert =
> +       "#version 130\n"
> +       "in vec2 pos;\n"
> +       "uniform float depth;\n"
> +       "void main()\n"
> +       "{\n"
> +       "  vec4 eye_pos = gl_ModelViewProjectionMatrix * vec4(pos, 0.0,
> 1.0);\n"
> +       "  gl_Position = vec4(eye_pos.xy, depth, 1.0);\n"
> +       "}\n";
> +
> +static const char *frag =
> +       "#version 130\n"
> +       "uniform vec4 color;\n"
> +       "void main()\n"
> +       "{\n"
> +       "  gl_FragColor = color;\n"
> +       "}\n";
> +
> +void
> +shader_compile()
> +{
> +       /* Compile program */
> +       GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
> +       GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
> +       prog = piglit_link_simple_program(vs, fs);
> +
> +       if (!piglit_link_check_status(prog)) {
> +               piglit_report_result(PIGLIT_FAIL);
> +       }
> +
> +       glBindAttribLocation(prog, 0, "pos");
> +       glEnableVertexAttribArray(0);
> +
> +       /* Set up uniforms */
> +       glUseProgram(prog);
> +       color_loc = glGetUniformLocation(prog, "color");
> +       depth_loc = glGetUniformLocation(prog, "depth");
> +}
> +
> +void
> +draw_pattern(bool sample_coverage, bool coverage_invert)
> +{
> +       float vertex_data[10][2] = {
> +               { 0,                     0 },
> +               { 0,                     pattern_height },
> +               { pattern_width / 4,     pattern_height },
> +               { pattern_width / 4,     0 },
> +               { pattern_width / 2,     pattern_height },
> +               { pattern_width / 2,     0 },
> +               { 3 * pattern_width / 4, pattern_height },
> +               { 3 * pattern_width / 4, 0 },
> +               { pattern_width,         pattern_height },
> +               { pattern_width,         0 },
> +       };
> +
> +       unsigned int indices[24] = {0, 1, 2, 0, 2, 3,
> +                                   3, 2, 4, 3, 4, 5,
> +                                   5, 4, 6, 5, 6, 7,
> +                                   7, 6, 8, 7, 8, 9};
> +       glUseProgram(prog);
> +       glClearColor(bg_color[0], bg_color[1],
> +                    bg_color[2], bg_color[3]);
> +
> +       glClear(buffer_to_test);
> +       if (sample_coverage)
> +               glEnable (GL_SAMPLE_COVERAGE);
> +
> +       glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,
> sizeof(vertex_data[0]),
> +                             (void *) vertex_data);
> +
> +       for (int i = 0; i < 4; ++i) {
> +               if(sample_coverage) {
> +                       if(coverage_invert)
> +                               glSampleCoverage (cov[i], GL_TRUE);
> +                       else
> +                               glSampleCoverage (cov[i], GL_FALSE);
> +               }
> +               glUniform4fv(color_loc, 1, color[i]);
> +               glUniform1f(depth_loc, depth[i]);
> +               glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,
> +                              (void *) (indices + 6 * i));
> +       }
> +       if(sample_coverage)
> +               glDisable (GL_SAMPLE_COVERAGE);
> +}
> +
> +void
> +print_usage_and_exit(char *prog_name)
> +{
> +       printf("Usage: %s <num_samples> <buffer_type>\n"
> +              "  where <buffer_type> is one of:\n"
> +              "    color\n"
> +              "    depth\n",
> +              prog_name);
> +       piglit_report_result(PIGLIT_FAIL);
> +}
> +
> +void
> +compute_expected(bool coverage_invert)
> +{
> +       int i, j;
> +       float coverage[4];
> +       if(coverage_invert) {
> +               for (i = 0; i < 4; i++)
> +                       coverage[i] = 1 - cov[i];
> +       }
> +       else
> +               for (i = 0; i < 4; i++)
> +                       coverage[i] = cov[i];
> +
> +       /* 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 will be blended
> +        * with the background color which will be 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."
> +        */
> +       if(buffer_to_test == GL_COLOR_BUFFER_BIT) {
> +               for (i = 0; i < 4; i++) {
> +                       for (j = 0; j < 4; j++)
> +                               expected[i][j] = color[i][j] * coverage[i]
> +
> +                                                bg_color[j] * (1 -
> coverage[i]);
> +               }
> +       }
> +       /* Compute the expected depth values only for coverage = 0.0 and
> 1.0 */
> +       else if(buffer_to_test == GL_DEPTH_BUFFER_BIT) {
> +               for (i = 0; i < 4; i++) {
> +                       if (coverage[i] == 0.0)
> +                               expected[0][i] = bg_depth;
> +                       else if (coverage[i] == 1.0)
> +                               expected[0][i] = depth[i] < bg_depth ?
> +                                                depth[i] : bg_depth;
> +               }
> +       }
> +}
> +
> +bool
> +probe_framebuffer_color(void)
> +{
> +       bool result = true;
> +       glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
> +       for (int i = 0; i < 4; i++) {
> +               result = piglit_probe_rect_rgba(i * (pattern_width / 4),
> +                                               0,
> +                                               pattern_width / 4,
> +                                               pattern_height,
> +                                               expected[i])
> +                        && result;
> +       }
> +       return result;
> +}
> +
> +bool
> +probe_framebuffer_depth(void)
> +{
> +       bool result = true;
> +       glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
> +       for (int i = 0; i < 4; i++) {
> +               if(cov[i] == 0.0 || cov[i] == 1.0)
> +                       result = piglit_probe_rect_depth(i *
> (pattern_width / 4),
> +                                                        0,
> +                                                        pattern_width / 4,
> +                                                        pattern_height,
> +                                                        expected[0][i])
> +                                && result;
> +               else
> +                       /*Skip probing polygons which are drawn with
> coverage
> +                       * value between 0.0 and 1.0
> +                       */
> +                       continue;
> +       }
> +       return result;
> +}
> +
> +bool
> +test_sample_coverage(bool coverage_invert)
> +{
> +       bool result = true;
> +       compute_expected(coverage_invert);
> +       /* Now draw test pattern in mulisample ms_fbo with
> GL_SAMPLE_COVERAGE
> +        * enabled
> +        */
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
> +       draw_pattern(true, coverage_invert);
> +
> +       /* Blit ms_fbo to resolve_fbo to resolve multisample buffer */
> +       glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo.handle);
> +       glBlitFramebuffer(0, 0, pattern_width, pattern_height,
> +                         0, 0, pattern_width, pattern_height,
> +                         buffer_to_test, GL_NEAREST);
> +
> +       /* Blit resolve_fbo to the left half of window system framebuffer.
> +        * This is the test image.
> +        */
> +       glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo.handle);
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
> +       glBlitFramebuffer(0, 0, pattern_width, pattern_height,
> +                         0, 0, pattern_width, pattern_height,
> +                         buffer_to_test, GL_NEAREST);
> +
> +       /* Probe the left half of default framebuffer and compare to the
> +        * expected values */
> +       if (buffer_to_test == GL_COLOR_BUFFER_BIT)
> +               result = probe_framebuffer_color() && result;
> +       else if (buffer_to_test == GL_DEPTH_BUFFER_BIT)
> +               result = probe_framebuffer_depth() && result;
> +
> +       result = piglit_check_gl_error(GL_NO_ERROR) && result;
> +       return result;
> +}
> +
> +void
> +piglit_init(int argc, char **argv)
> +{
> +       if (argc < 3)
> +               print_usage_and_exit(argv[0]);
> +       {
> +               char *endptr = NULL;
> +               num_samples = strtol(argv[1], &endptr, 0);
> +               if (endptr != argv[1] + strlen(argv[1]))
> +                       print_usage_and_exit(argv[0]);
> +       }
> +
> +       piglit_require_gl_version(30);
> +       glClear(GL_COLOR_BUFFER_BIT);
>

This call to glClear() is unnecessary, since you also call glClear() at the
beginning of piglit_display().  It's also confusing, because drawing calls
shouldn't be in piglit_init() anyhow.


> +       piglit_ortho_projection(pattern_width, pattern_height, GL_TRUE);
> +
> +       /* Skip the test if num_samples > GL_MAX_SAMPLES or num_samples =
> 0 */
> +       GLint max_samples;
> +       glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
> +       if (num_samples > max_samples ||
> +           num_samples == 0)
> +               piglit_report_result(PIGLIT_SKIP);
>

Skipping if num_samples > max_samples makes sense, because we only want the
test to run for supported sample counts.  But skipping if num_samples == 0
is weird, since num_samples is specified by the user when invoking the
test.  My recommendation would be to let the test go ahead and execute even
if num_samples == 0, because it's sometimes handy in debugging to invoke an
MSAA test with num_samples == 0 just to see what will happen (even if the
test is expected to fail).


> +
> +       ms_fbo.setup(FboConfig(num_samples, pattern_width,
> pattern_height));
> +       resolve_fbo.setup(FboConfig(0, pattern_width, pattern_height));
> +
> +       if (strcmp(argv[2], "color") == 0) {
> +               buffer_to_test = GL_COLOR_BUFFER_BIT;
> +       } else if (strcmp(argv[2], "depth") == 0) {
> +               buffer_to_test = GL_DEPTH_BUFFER_BIT;
> +               glClearDepth(bg_depth);
> +               glEnable(GL_DEPTH_TEST);
> +       } else
> +               print_usage_and_exit(argv[0]);
> +
> +       shader_compile();
> +}
> +
> +enum piglit_result
> +piglit_display()
> +{
> +       bool pass = true;
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
> +       glClearColor(0.0, 0.0, 0.0, 1.0);
> +       glClear(GL_COLOR_BUFFER_BIT);
> +
> +       /* Draw test pattern in  multisample ms_fbo with GL_SAMPLE_COVERAGE
> +        * disabled.
> +        */
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
> +       ms_fbo.set_viewport();
> +       draw_pattern(false, false);
> +
> +       /* Blit ms_fbo to the right half of window system framebuffer. This
> +        * is a reference image to test MSAA with sample coverage.
> +        */
> +       glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);
> +       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
> +       glBlitFramebuffer(0, 0, pattern_width, pattern_height,
> +                         pattern_width, 0, 2 * pattern_width,
> pattern_height,
> +                         buffer_to_test, GL_NEAREST);
> +
> +       /* Test with coverage_invert = false */
> +       pass = test_sample_coverage(false) && pass;
> +
> +       /* Test with coverage_invert = true */
> +       pass = test_sample_coverage(true) && pass;
> +
> +       if (!piglit_automatic &&
> +           buffer_to_test != GL_DEPTH_BUFFER_BIT)
> +               piglit_present_results();
> +
> +       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
> +}
> --
> 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/20120616/de123c9a/attachment-0001.html>


More information about the Piglit mailing list