diff options
-rw-r--r-- | tests/all.tests | 15 | ||||
-rw-r--r-- | tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt | 1 | ||||
-rw-r--r-- | tests/spec/ext_framebuffer_multisample/common.cpp | 132 | ||||
-rw-r--r-- | tests/spec/ext_framebuffer_multisample/common.h | 38 | ||||
-rw-r--r-- | tests/spec/ext_framebuffer_multisample/interpolation.cpp | 453 |
5 files changed, 638 insertions, 1 deletions
diff --git a/tests/all.tests b/tests/all.tests index a533a0aa8..63937b964 100644 --- a/tests/all.tests +++ b/tests/all.tests @@ -1442,6 +1442,21 @@ for num_samples in MSAA_SAMPLE_COUNTS: ext_framebuffer_multisample[test_name] = PlainExecTest( executable) +# Note: the interpolation tests also check for sensible behaviour with +# non-multisampled framebuffers, so go ahead and test them with +# num_samples==0 as well. +for num_samples in (0,) + MSAA_SAMPLE_COUNTS: + for test_type in ('non-centroid-disabled', 'centroid-disabled', + 'centroid-edges', 'non-centroid-deriv', + 'non-centroid-deriv-disabled', 'centroid-deriv', + 'centroid-deriv-disabled'): + test_name = ' '.join(['interpolation', str(num_samples), + test_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 338a5e8e4..4eca40062 100644 --- a/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt +++ b/tests/spec/ext_framebuffer_multisample/CMakeLists.gl.txt @@ -18,6 +18,7 @@ piglit_add_executable (ext_framebuffer_multisample-clip-and-scissor-blit common. piglit_add_executable (ext_framebuffer_multisample-dlist dlist.c) piglit_add_executable (ext_framebuffer_multisample-enable-flag enable-flag.cpp common.cpp) piglit_add_executable (ext_framebuffer_multisample-formats common.cpp formats.cpp) +piglit_add_executable (ext_framebuffer_multisample-interpolation common.cpp interpolation.cpp) piglit_add_executable (ext_framebuffer_multisample-line-smooth common.cpp line-smooth.cpp) piglit_add_executable (ext_framebuffer_multisample-minmax minmax.c) piglit_add_executable (ext_framebuffer_multisample-multisample-blit common.cpp multisample-blit.cpp) diff --git a/tests/spec/ext_framebuffer_multisample/common.cpp b/tests/spec/ext_framebuffer_multisample/common.cpp index e0b5e2297..e1f6127fc 100644 --- a/tests/spec/ext_framebuffer_multisample/common.cpp +++ b/tests/spec/ext_framebuffer_multisample/common.cpp @@ -691,6 +691,138 @@ void Triangles::draw(const float (*proj)[4]) } } + +InterpolationTestPattern::InterpolationTestPattern(const char *frag) + : frag(frag) +{ +} + + +void +InterpolationTestPattern::compile() +{ + static struct vertex_attributes { + float pos_within_tri[2]; + float barycentric_coords[3]; + } vertex_data[] = { + { { -0.5, -1.0 }, { 1, 0, 0 } }, + { { 0.0, 1.0 }, { 0, 1, 0 } }, + { { 0.5, -1.0 }, { 0, 0, 1 } } + }; + + /* Number of triangle instances across (and down) */ + int tris_across = 8; + + /* Total number of triangles drawn */ + num_tris = tris_across * tris_across; + + /* Scaling factor uniformly applied to triangle coords */ + float tri_scale = 0.8 / tris_across; + + /* Amount each triangle should be rotated compared to prev */ + float rotation_delta = M_PI * 2.0 / num_tris; + + /* Final scaling factor */ + float final_scale = 0.95; + + static const char *vert = + "#version 130\n" + "in vec2 pos_within_tri;\n" + "in vec3 in_barycentric_coords;\n" + "out vec3 barycentric_coords;\n" + "centroid out vec3 barycentric_coords_centroid;\n" + "out vec2 pixel_pos;\n" + "centroid out vec2 pixel_pos_centroid;\n" + "uniform float tri_scale;\n" + "uniform float rotation_delta;\n" + "uniform int tris_across;\n" + "uniform float final_scale;\n" + "uniform mat4 proj;\n" + "uniform int tri_num; /* [0, num_tris) */\n" + "uniform ivec2 viewport_size;\n" + "\n" + "void main()\n" + "{\n" + " vec2 pos = tri_scale * pos_within_tri;\n" + " float rotation = rotation_delta * tri_num;\n" + " pos = mat2(cos(rotation), sin(rotation),\n" + " -sin(rotation), cos(rotation)) * pos;\n" + " int i = tri_num % tris_across;\n" + " int j = tris_across - 1 - tri_num / tris_across;\n" + " pos += (vec2(i, j) * 2.0 + 1.0) / tris_across - 1.0;\n" + " pos *= final_scale;\n" + " gl_Position = proj * vec4(pos, 0.0, 1.0);\n" + " barycentric_coords = barycentric_coords_centroid =\n" + " in_barycentric_coords;\n" + " pixel_pos = pixel_pos_centroid =\n" + " vec2(viewport_size) * (pos + 1.0) / 2.0;\n" + "}\n"; + + /* Compile program */ + prog = glCreateProgram(); + GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert); + glAttachShader(prog, vs); + GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag); + glAttachShader(prog, fs); + glBindAttribLocation(prog, 0, "pos_within_tri"); + glBindAttribLocation(prog, 1, "in_barycentric_coords"); + glLinkProgram(prog); + if (!piglit_link_check_status(prog)) { + piglit_report_result(PIGLIT_FAIL); + } + + /* Set up uniforms */ + glUseProgram(prog); + glUniform1f(glGetUniformLocation(prog, "tri_scale"), tri_scale); + glUniform1f(glGetUniformLocation(prog, "rotation_delta"), + rotation_delta); + glUniform1i(glGetUniformLocation(prog, "tris_across"), tris_across); + glUniform1f(glGetUniformLocation(prog, "final_scale"), final_scale); + proj_loc = glGetUniformLocation(prog, "proj"); + tri_num_loc = glGetUniformLocation(prog, "tri_num"); + viewport_size_loc = glGetUniformLocation(prog, "viewport_size"); + + /* Set up vertex array object */ + glGenVertexArrays(1, &vao); + glBindVertexArray(vao); + + /* Set up vertex input buffer */ + glGenBuffers(1, &vertex_buf); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buf); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, + GL_STATIC_DRAW); + glEnableVertexAttribArray(0); + glVertexAttribPointer(0, ARRAY_SIZE(vertex_data[0].pos_within_tri), + GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]), + (void *) offsetof(vertex_attributes, + pos_within_tri)); + glEnableVertexAttribArray(1); + glVertexAttribPointer(1, ARRAY_SIZE(vertex_data[0].barycentric_coords), + GL_FLOAT, GL_FALSE, sizeof(vertex_data[0]), + (void *) offsetof(vertex_attributes, + barycentric_coords)); +} + + +void +InterpolationTestPattern::draw(const float (*proj)[4]) +{ + glUseProgram(prog); + + /* Depending what the fragment shader does, it's possible that + * viewport_size might get optimized away. Only set it if it + * didn't. + */ + if (viewport_size_loc != -1) { + GLint viewport_dims[4]; + glGetIntegerv(GL_VIEWPORT, viewport_dims); + glUniform2i(viewport_size_loc, viewport_dims[2], viewport_dims[3]); + } + + Triangles::draw(proj); +} + + void Lines::compile() { /* Line coords within (-1,-1) to (1,1) rect */ diff --git a/tests/spec/ext_framebuffer_multisample/common.h b/tests/spec/ext_framebuffer_multisample/common.h index 12344b6a7..dd0937020 100644 --- a/tests/spec/ext_framebuffer_multisample/common.h +++ b/tests/spec/ext_framebuffer_multisample/common.h @@ -245,7 +245,7 @@ public: virtual void compile(); virtual void draw(const float (*proj)[4]); -private: +protected: GLint prog; GLuint vertex_buf; GLuint vao; @@ -254,6 +254,42 @@ private: int num_tris; }; + +/** + * Program we use to test that interpolation works properly. + * + * This program draws the same sequence of small triangles as the + * Triangles program, but it's capable of coloring the triangles in + * various ways based on the fragment program provided to the + * constructor. + * + * The fragment program has access to the following variables: + * + * - in vec3 barycentric_coords: barycentric coordinates of the + * triangle being drawn, normally interpolated. + * + * - centroid in vec3 barycentric_coords_centroid: same as + * barycentric_coords, but centroid interpolated. + * + * - in vec2 pixel_pos: pixel coordinate ((0,0) to (viewport_width, + * viewport_height)), normally interpolated. + * + * - centroid in vec2 pixel_pos_centroid: same as pixel_pos, but + * centroid interpolated. + */ +class InterpolationTestPattern : public Triangles +{ +public: + explicit InterpolationTestPattern(const char *frag); + virtual void compile(); + virtual void draw(const float (*proj)[4]); + +private: + const char *frag; + GLint viewport_size_loc; +}; + + /** * Program we use to draw a test pattern into the color buffer. * diff --git a/tests/spec/ext_framebuffer_multisample/interpolation.cpp b/tests/spec/ext_framebuffer_multisample/interpolation.cpp new file mode 100644 index 000000000..45db66f21 --- /dev/null +++ b/tests/spec/ext_framebuffer_multisample/interpolation.cpp @@ -0,0 +1,453 @@ +/* + * 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. + */ + +/** + * \file interpolation.cpp + * + * Verify that the implementation interpolates varyings correctly when + * multisampling is in use, particularly that it properly implements + * the "centroid" keyword. + * + * From the GLSL 1.30 spec, section 4.3.7 (Interpolation): + * + * "This paragraph only applies if interpolation is being done: If + * single-sampling, the value is interpolated to the pixel's + * center, and the centroid qualifier, if present, is ignored. If + * multi-sampling and the variable is not qualified with centroid, + * then the value must be interpolated to the pixel's center, or + * anywhere within the pixel, or to one of the pixel's samples. If + * multi-sampling and the variable is qualified with centroid, + * then the value must be interpolated to a point that lies in + * both the pixel and in the primitive being rendered, or to one + * of the pixel's samples that falls within the primitive. Due to + * the less regular location of centroids, their derivatives may + * be less accurate than non-centroid interpolated variables." + * + * + * This test accepts two command-line parameters, a value for + * num_samples, and a test type. The test types are as follows: + * + * - non-centroid-disabled: verify that non-centroid interpolation + * produces the same results when applied to a non-multisampled + * buffer and a multisampled buffer with GL_MULTISAMPLE disabled. + * This effectively verifies that non-centroid varyings are + * interpolated at the pixel center when single-sampling. The test + * uses a fragment shader that sets the red, green, and blue + * channels to the barycentric coordinates within each triangle. + * + * - centroid-disabled: verify that centroid interpolation produces + * the same results as non-centroid interpolation when applied to a + * multisampled buffer with GL_MULTISAMPLE disabled. This + * effectively verifies that centroid varyings are interpolated at + * the pixel center when single-sampling. This test may also be run + * with num_samples=0 to verify that centroid varyings work properly + * in non-multisampled buffers. The test uses a fragment shader + * that sets the red, green, and blue channels to the barycentric + * coordinates within each triangle. + * + * - centroid-edges: verify that centroid interpolation occurs at + * points that lie within the extents of the triangle, even for + * pixels on triangle edges, where the center of the pixel might lie + * outside the extents of the triangle. The test uses a fragment + * shader that sets the blue channel to 1.0 (so that the triangles + * can be seen) and the red and green channels to 1.0 if any of the + * centroid-interpolated barycentric coordinates is outside the + * range [0, 1]. + * + * - non-centroid-deriv: verify that the numeric derivative of a + * varying using non-centroid interpolation is correct, even at + * triangle edges. This ensures that the implementation properly + * handles a subtle corner case: since numeric derivatives are + * usually computed using finite differences between adjacent + * pixels, it's possible that the value of a varying at a completely + * uncovered pixel might be used. In effect, this tests that the + * values of varyings are correct on completely uncovered pixels, if + * those values are needed for derivatives. This test may also be + * run with num_samples=0 to verify that non-centroid varyings + * exhibit proper derivative behaviour in non-multisampled buffers. + * The test uses a fragment shader that sets red=dFdx(interpolated x + * coordinate), green=dFdy(interpolated y coordinate), and blue=1.0, + * with appropriate scaling applied to the red and green outputs so + * that the expected output is red=0.5 and green=0.5. + * + * - non-centroid-deriv-disabled: Like non-centroid-deriv, but the + * test is done with GL_MULTISAMPLE disabled. + * + * - centroid-deriv: verify that the numeric derivative of a vaying + * using centroid interpolation is within reasonable bounds. Any + * derivative value between 0 and twice the expected derivative is + * considered passing, since this is the expected error bound for a + * typical implementation (where derivative is computed via a finite + * difference of adjacent pixels, and sample points are within the + * pixel boundary). As with non-centroid-deriv, this test may also + * be run with num_samples=0 to verify that centroid varyings + * exhibit proper derivative behaviour in non-multisampled buffers; + * in this case, the error bounds are as in non-centroid-deriv, + * since centroid-related derivative errors are not expected. When + * num_samples=0, the fragment shader generates outputs as in + * non-centroid-deriv. Otherwise it sets the blue channel to 1.0 + * (so that the triangles can be seen) and the red nd green channels + * to 1.0 if either derivative is out of tolerance. + * + * - centroid-deriv-disabled: like centroid-deriv, but the test is + * done with GL_MULTISAMPLE disabled, and the error bounds are as in + * non-centroid-deriv. The fragment shader generates outputs as in + * non-centroid-deriv. + * + * All test types draw an array of small triangles at various + * rotations, so that pixels are covered in a wide variety of + * patterns. In each case the rendered result is displayed on the + * left, and the expected result is displayed on the right for + * comparison. + */ + +#include "common.h" + +PIGLIT_GL_TEST_MAIN( + 512 /*window_width*/, + 256 /*window_height*/, + GLUT_DOUBLE | GLUT_RGBA | GLUT_ALPHA) + +namespace { + +const int pattern_width = 256; const int pattern_height = 256; + +Fbo singlesampled_fbo; +Fbo multisampled_fbo; + + +/** + * Test pattern that we'll use to draw the test image. + */ +TestPattern *test_pattern; + + +/** + * Test pattern that we'll use to draw the reference image. + */ +TestPattern *ref_pattern; + + +/** + * If true, we will disable GL_MULTISAMPLE while drawing the test + * image, and we will draw the reference image into a single-sample + * buffer. + */ +bool disable_msaa_during_test_image = false; + + +/** + * Fragment shader source that sets the red, green, and blue channels + * to the non-centroid-interpolated barycentric coordinates within + * each triangle. + */ +const char *frag_non_centroid_barycentric = + "#version 130\n" + "in vec3 barycentric_coords;\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(barycentric_coords, 1.0);\n" + "}\n"; + + +/** + * Fragment shader source that sets the red, green, and blue channels + * to the centroid-interpolated barycentric coordinates within each + * triangle. + */ +const char *frag_centroid_barycentric = + "#version 130\n" + "centroid in vec3 barycentric_coords_centroid;\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(barycentric_coords_centroid, 1.0);\n" + "}\n"; + + +/** + * Fragment shader source that sets the blue channel to 1.0, and the + * red and green channels to 1.0 if any of the centroid-interpolated + * barycentric coordinates is outside the range [0, 1]. + */ +const char *frag_centroid_range_check = + "#version 130\n" + "centroid in vec3 barycentric_coords_centroid;\n" + "\n" + "void main()\n" + "{\n" + " if (any(greaterThan(barycentric_coords_centroid, vec3(1.0))) ||\n" + " any(lessThan(barycentric_coords_centroid, vec3(0.0))))\n" + " gl_FragColor = vec4(1.0);\n" + " else\n" + " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" + "}\n"; + + +/** + * Fragment shader source that sets red=dFdx(interpolated x + * coordinate), green=dFdy(interpolated y coordinate), and blue=1.0, + * with appropriate scaling applied to the red and green outputs so + * that the expected output is red=0.5 and green=0.5. The coordinates + * are non-centroid interpolated. + */ +const char *frag_non_centroid_deriv = + "#version 130\n" + "in vec2 pixel_pos;\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(0.5*dFdx(pixel_pos.x),\n" + " 0.5*dFdy(pixel_pos.y),\n" + " 1.0, 1.0);\n" + "}\n"; + + +/** + * Fragment shader source that sets red=dFdx(interpolated x + * coordinate), green=dFdy(interpolated y coordinate), and blue=1.0, + * with appropriate scaling applied to the red and green outputs so + * that the expected output is red=0.5 and green=0.5. The coordinates + * are non-centroid interpolated. + */ +const char *frag_centroid_deriv = + "#version 130\n" + "centroid in vec2 pixel_pos_centroid;\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(0.5*dFdx(pixel_pos_centroid.x),\n" + " 0.5*dFdy(pixel_pos_centroid.y),\n" + " 1.0, 1.0);\n" + "}\n"; + + +/** + * Fragment shader source that sets the blue channel to 1.0, and the + * red and green channels to 1.0 if either derivative is out of + * tolerance. + */ +const char *frag_centroid_deriv_range_check = + "#version 130\n" + "centroid in vec2 pixel_pos_centroid;\n" + "\n" + "void main()\n" + "{\n" + " if (distance(1.0, dFdx(pixel_pos_centroid.x)) > 1.0 ||\n" + " distance(1.0, dFdy(pixel_pos_centroid.y)) > 1.0)\n" + " gl_FragColor = vec4(1.0);\n" + " else\n" + " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" + "}\n"; + + +/** + * Fragment shader source that outputs blue (the expected output of + * frag_centroid_range_check and frag_centroid_deriv_range_check). + */ +const char *frag_blue = + "#version 130\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" + "}\n"; + + +/** + * Fragment shader source that sets red=0.5, green=0.5, and blue=1.0 + * (the expected output of frag_non_centroid_deriv and + * frag_centroid_deriv). + */ +const char *frag_rg_0_5 = + "#version 130\n" + "\n" + "void main()\n" + "{\n" + " gl_FragColor = vec4(0.5, 0.5, 1.0, 1.0);\n" + "}\n"; + + +void +print_usage_and_exit(char *prog_name) +{ + printf("Usage: %s <num_samples> <test_type>\n" + " where <test_type> is one of:\n" + " non-centroid-disabled: non-centroid varying, MSAA off\n" + " centroid-disabled: centroid varying, MSAA off\n" + " centroid-edges: centroid behaviour at trinagle edges\n" + " non-centroid-deriv: dFdx/dFdy on non-centroid varying\n" + " non-centroid-deriv-disabled: As above, with MSAA off\n" + " centroid-deriv: dFdx/dFdy on centroid varying\n" + " centroid-deriv-disabled: As above, with MSAA off\n", + prog_name); + piglit_report_result(PIGLIT_FAIL); +} + +extern "C" void +piglit_init(int argc, char **argv) +{ + if (argc != 3) + print_usage_and_exit(argv[0]); + + /* 1st arg: num_samples */ + char *endptr = NULL; + int num_samples = strtol(argv[1], &endptr, 0); + if (endptr != argv[1] + strlen(argv[1])) + print_usage_and_exit(argv[0]); + + /* 2nd arg: test_type */ + const char *frag; /* Fragment shader for the test image */ + const char *ref_frag; /* Fragment shader for the reference image */ + if (strcmp(argv[2], "non-centroid-disabled") == 0) { + frag = frag_non_centroid_barycentric; + ref_frag = frag_non_centroid_barycentric; + disable_msaa_during_test_image = true; + } else if (strcmp(argv[2], "centroid-disabled") == 0) { + frag = frag_centroid_barycentric; + ref_frag = frag_non_centroid_barycentric; + disable_msaa_during_test_image = true; + } else if (strcmp(argv[2], "centroid-edges") == 0) { + frag = frag_centroid_range_check; + ref_frag = frag_blue; + } else if (strcmp(argv[2], "non-centroid-deriv") == 0) { + frag = frag_non_centroid_deriv; + ref_frag = frag_rg_0_5; + } else if (strcmp(argv[2], "non-centroid-deriv-disabled") == 0) { + frag = frag_non_centroid_deriv; + ref_frag = frag_rg_0_5; + disable_msaa_during_test_image = true; + } else if (strcmp(argv[2], "centroid-deriv") == 0) { + if (num_samples == 0) { + frag = frag_centroid_deriv; + ref_frag = frag_rg_0_5; + } else { + frag = frag_centroid_deriv_range_check; + ref_frag = frag_blue; + } + } else if (strcmp(argv[2], "centroid-deriv-disabled") == 0) { + frag = frag_centroid_deriv; + ref_frag = frag_rg_0_5; + disable_msaa_during_test_image = true; + } else { + print_usage_and_exit(argv[0]); + } + + piglit_require_gl_version(30); + + /* Skip the test if num_samples > GL_MAX_SAMPLES */ + GLint max_samples; + glGetIntegerv(GL_MAX_SAMPLES, &max_samples); + if (num_samples > max_samples) + piglit_report_result(PIGLIT_SKIP); + + singlesampled_fbo.setup(FboConfig(0, pattern_width, + pattern_height)); + multisampled_fbo.setup(FboConfig(num_samples, pattern_width, + pattern_height)); + test_pattern = new InterpolationTestPattern(frag); + test_pattern->compile(); + ref_pattern = new InterpolationTestPattern(ref_frag); + ref_pattern->compile(); + + if (!piglit_check_gl_error(GL_NO_ERROR)) + piglit_report_result(PIGLIT_FAIL); +} + +extern "C" enum piglit_result +piglit_display() +{ + bool pass = true; + + /* Draw the test pattern into the multisampled buffer, + * disabling MSAA if appropriate. + */ + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, multisampled_fbo.handle); + multisampled_fbo.set_viewport(); + if (disable_msaa_during_test_image) + glDisable(GL_MULTISAMPLE); + test_pattern->draw(TestPattern::no_projection); + if (disable_msaa_during_test_image) + glEnable(GL_MULTISAMPLE); + + /* Blit the test pattern to the single-sampled buffer to force + * a resolve. + */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, multisampled_fbo.handle); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, singlesampled_fbo.handle); + glBlitFramebuffer(0, 0, pattern_width, pattern_height, + 0, 0, pattern_width, pattern_height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + + /* Blit the test pattern to the left half of the piglit window. */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, singlesampled_fbo.handle); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, pattern_width, pattern_height, + 0, 0, pattern_width, pattern_height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + + /* Draw the reference pattern. If we disabled GL_MULTISAMPLE + * while drawing the test pattern, then draw the reference + * pattern into a single-sampled buffer so that multisampling + * won't take place; otherwise draw the reference pattern into + * the multisampled buffer. + */ + Fbo *draw_fbo = disable_msaa_during_test_image ? + &singlesampled_fbo : &multisampled_fbo; + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, draw_fbo->handle); + draw_fbo->set_viewport(); + ref_pattern->draw(TestPattern::no_projection); + + /* If we drew the reference pattern into the multisampled + * buffer, blit to the single-sampled buffer to force a + * resolve. + */ + if (!disable_msaa_during_test_image) { + glBindFramebuffer(GL_READ_FRAMEBUFFER, + multisampled_fbo.handle); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, + singlesampled_fbo.handle); + glBlitFramebuffer(0, 0, pattern_width, pattern_height, + 0, 0, pattern_width, pattern_height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + } + + /* Blit the reference image to the right half of the piglit window. */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, singlesampled_fbo.handle); + glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); + glBlitFramebuffer(0, 0, pattern_width, pattern_height, + pattern_width, 0, 2*pattern_width, pattern_height, + GL_COLOR_BUFFER_BIT, GL_NEAREST); + + /* Compare the test pattern to the reference image. */ + glBindFramebuffer(GL_READ_FRAMEBUFFER, 0); + pass = piglit_probe_rect_halves_equal_rgba(0, 0, 2*pattern_width, + pattern_height) && pass; + + piglit_present_results(); + + return pass ? PIGLIT_PASS : PIGLIT_FAIL; +} + +} /* Anonymous namespace */ |