diff options
author | Paul Berry <stereotype441@gmail.com> | 2012-06-07 11:55:05 -0700 |
---|---|---|
committer | Paul Berry <stereotype441@gmail.com> | 2012-06-25 11:13:07 -0700 |
commit | 98d1e497014626237f0d9a5f3343ac3d8d4e7698 (patch) | |
tree | 404eac0df9c2b97c198e0aafa061fd08534196b4 /tests/spec/ext_framebuffer_multisample/common.cpp | |
parent | 1d513da8c56ef3b0d0823da377b5d1606cc07f39 (diff) |
msaa: Verify accuracy of sRGB MSAA resolves.
From the GL spec, version 4.2, section 4.1.11 (Additional Multisample
Fragment Operations):
If a framebuffer object is not bound, after all operations have
been completed on the multisample buffer, the sample values for
each color in the multisample buffer are combined to produce a
single color value, and that value is written into the
corresponding color buffers selected by DrawBuffer or
DrawBuffers. An implementation may defer the writing of the color
buffers until a later time, but the state of the framebuffer must
behave as if the color buffers were updated as each fragment was
processed. The method of combination is not specified. If the
framebuffer contains sRGB values, then it is recommended that the
an average of sample values is computed in a linearized space, as
for blending (see section 4.1.7).
This patch adds a new "srgb" mode to the MSAA accuracy test, which
verifies that the formula used by the implementation to blend sRGB
samples matches the GL spec's recommendations. When an "srgb"
accuracy test is requested, the test is modified to do the following
things:
- Render using a buffer format of SRGB8_ALPHA8 instead of RGBA.
- When manually downsampling the reference image, enable
FRAMEBUFFER_SRGB, so that the data output by the manual downsampler
gets converted from linear color space into sRGB color space. This
ensures that the reference image is generated according to the
spec's recommendations.
- Convert pixels from sRGB color space to linear color space before
comparing the test image and the reference image. This ensures that
the RMS error is computed in linear color space, so that the RMS
error computed for sRGB mode is comparable with the RMS error
computed for linear RGBA color.
Note: if an implementation fails this test, that does not necessarily
mean that it fails to meet the GL spec (since the spec only recommends
sRGB-correct averaging, it doesn't require it). For example, the
nVidia closed-source driver for Linux fails this test.
Reviewed-by: Anuj Phogat <anuj.phogat@gmail.com>
Diffstat (limited to 'tests/spec/ext_framebuffer_multisample/common.cpp')
-rw-r--r-- | tests/spec/ext_framebuffer_multisample/common.cpp | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/tests/spec/ext_framebuffer_multisample/common.cpp b/tests/spec/ext_framebuffer_multisample/common.cpp index e1060a862..c21136339 100644 --- a/tests/spec/ext_framebuffer_multisample/common.cpp +++ b/tests/spec/ext_framebuffer_multisample/common.cpp @@ -342,7 +342,8 @@ DownsampleProg::compile(int supersample_factor) } void -DownsampleProg::run(const Fbo *src_fbo, int dest_width, int dest_height) +DownsampleProg::run(const Fbo *src_fbo, int dest_width, int dest_height, + bool srgb) { float w = dest_width; float h = dest_height; @@ -363,7 +364,15 @@ DownsampleProg::run(const Fbo *src_fbo, int dest_width, int dest_height) glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STREAM_DRAW); + if (srgb) { + /* If we're testing sRGB color, instruct OpenGL to + * convert the output of the fragment shader from + * linear color space to sRGB color space. + */ + glEnable(GL_FRAMEBUFFER_SRGB); + } glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, (void *) 0); + glDisable(GL_FRAMEBUFFER_SRGB); } void @@ -1156,11 +1165,12 @@ Stats::is_better_than(double rms_error_threshold) } Test::Test(TestPattern *pattern, ManifestProgram *manifest_program, - bool test_resolve, GLbitfield blit_type) + bool test_resolve, GLbitfield blit_type, bool srgb) : pattern(pattern), manifest_program(manifest_program), test_resolve(test_resolve), - blit_type(blit_type) + blit_type(blit_type), + srgb(srgb) { } @@ -1176,6 +1186,8 @@ Test::init(int num_samples, bool small, bool combine_depth_stencil, FboConfig test_fbo_config(0, small ? 16 : pattern_width, small ? 16 : pattern_height); + if (srgb) + test_fbo_config.color_internalformat = GL_SRGB8_ALPHA8; test_fbo_config.combine_depth_stencil = combine_depth_stencil; test_fbo.setup(test_fbo_config); @@ -1235,7 +1247,7 @@ Test::downsample_color(int downsampled_width, int downsampled_height) downsample_fbo.set_viewport(); downsample_prog.run(&supersample_fbo, downsample_fbo.config.width, - downsample_fbo.config.height); + downsample_fbo.config.height, srgb); } /** @@ -1371,6 +1383,20 @@ Test::draw_reference_image() } /** + * Convert from sRGB color space to linear color space, using the + * formula from the GL 3.0 spec, section 4.1.8 (sRGB Texture Color + * Conversion). + */ +float +decode_srgb(float x) +{ + if (x <= 0.0405) + return x / 12.92; + else + return pow((x + 0.055) / 1.055, 2.4); +} + +/** * Measure the accuracy of MSAA downsampling. Pixels that are fully * on or off in the reference image are required to be fully on or off * in the test image. Pixels that are not fully on or off in the @@ -1403,6 +1429,14 @@ Test::measure_accuracy() int pixel_pos = 4*(y*pattern_width + x) + c; float ref = reference_data[pixel_pos]; float test = test_data[pixel_pos]; + /* When testing sRGB, compare pixels + * linearly so that the measured error + * is comparable to the non-sRGB case. + */ + if (srgb && c < 3) { + ref = decode_srgb(ref); + test = decode_srgb(test); + } if (ref <= 0.0) unlit_stats.record(test - ref); else if (ref >= 1.0) @@ -1464,29 +1498,32 @@ create_test(test_type_enum test_type, int n_samples, bool small, Test *test = NULL; switch (test_type) { case TEST_TYPE_COLOR: - test = new Test(new Triangles(), NULL, false, 0); + test = new Test(new Triangles(), NULL, false, 0, false); + break; + case TEST_TYPE_SRGB: + test = new Test(new Triangles(), NULL, false, 0, true); break; case TEST_TYPE_STENCIL_DRAW: test = new Test(new StencilSunburst(), new ManifestStencil(), - false, 0); + false, 0, false); break; case TEST_TYPE_STENCIL_RESOLVE: test = new Test(new StencilSunburst(), new ManifestStencil(), true, - GL_STENCIL_BUFFER_BIT); + GL_STENCIL_BUFFER_BIT, false); break; case TEST_TYPE_DEPTH_DRAW: test = new Test(new DepthSunburst(), new ManifestDepth(), - false, 0); + false, 0, false); break; case TEST_TYPE_DEPTH_RESOLVE: test = new Test(new DepthSunburst(), new ManifestDepth(), true, - GL_DEPTH_BUFFER_BIT); + GL_DEPTH_BUFFER_BIT, false); break; default: printf("Unrecognized test type\n"); |