2 * Copyright © 2013 VMware, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24 * Roland Scheidegger <sroland@vmware.com>
26 * Tests accuracy of srgb->linear and linear->srgb conversion,
27 * according to d3d10 rules:
28 * 1) srgb->linear is permitted a tolerance of 0.5 on the srgb side
29 * (meaning the result converted back to srgb (but before float->int
30 * conversion) using perfect formula must not deviate more than 0.5)
31 * 2) linear->srgb is permitted a tolerance of 0.6 compared to using
33 * 3) additionally all srgb values must stay the same when doing
34 * srgb to linear and then linear to srgb conversion.
35 * This test does not actually verify 2) (which would need exhaustive
36 * test of all float values) so if some floats outside these generated
37 * by srgb->linear conversion get mapped to arbitrary values that will
38 * go unnoticed. Likewise, correct behavior for floats outside 0.0-1.0
39 * is not verified (including INFs and NaNs - the former should get clamped
40 * to 0/255 in the end, NaNs should also get mapped to 0).
44 #include "piglit-util-gl.h"
46 PIGLIT_GL_TEST_CONFIG_BEGIN
48 config
.supports_gl_compat_version
= 10;
50 config
.window_width
= 16;
51 config
.window_height
= 16;
52 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
54 PIGLIT_GL_TEST_CONFIG_END
56 static enum piglit_result
test_format(void)
60 GLuint texsrgb
, texfb
, fb
;
63 float tex_vals
[256][4];
66 GLubyte readb
[256][4];
69 for (i
= 0; i
< 256; i
++) {
70 tex_vals
[i
][0] = (float)i
/ 255.0f
;
71 tex_vals
[i
][1] = tex_vals
[i
][2] = 0.0f
;
72 tex_vals
[i
][3] = 1.0f
;
75 /* initialize texture */
76 glGenTextures(1, &texsrgb
);
77 glBindTexture(GL_TEXTURE_2D
, texsrgb
);
78 glTexImage2D(GL_TEXTURE_2D
, 0, GL_SRGB8_ALPHA8_EXT
,
80 GL_RGBA
, GL_FLOAT
, &tex_vals
[0][0]);
82 glGenFramebuffersEXT(1, &fb
);
83 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT
, fb
);
84 glViewport(0, 0, piglit_width
, piglit_height
);
86 /* draw into float framebuffer and verify results */
87 glGenTextures(1, &texfb
);
88 glBindTexture(GL_TEXTURE_2D
, texfb
);
89 glTexImage2D(GL_TEXTURE_2D
, 0, GL_RGBA32F_ARB
,
90 piglit_width
, piglit_height
, 0,
91 GL_RGBA
, GL_FLOAT
, NULL
);
93 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
,
94 GL_COLOR_ATTACHMENT0_EXT
,
98 if (!piglit_check_gl_error(GL_NO_ERROR
))
99 piglit_report_result(PIGLIT_FAIL
);
101 status
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
102 printf("Testing using fb float format");
103 if (status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
104 printf(" - fbo incomplete (status = %s)\n",
105 piglit_get_gl_enum_name(status
));
106 piglit_report_subtest_result(PIGLIT_SKIP
, "float fb");
111 glColor4f(1, 1, 1, 1);
112 glEnable(GL_TEXTURE_2D
);
113 glBindTexture(GL_TEXTURE_2D
, texsrgb
);
115 glTexEnvi(GL_TEXTURE_ENV
, GL_TEXTURE_ENV_MODE
, GL_COMBINE
);
116 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_RGB
, GL_REPLACE
);
117 glTexEnvi(GL_TEXTURE_ENV
, GL_COMBINE_ALPHA
, GL_REPLACE
);
119 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MIN_FILTER
, GL_NEAREST
);
120 glTexParameteri(GL_TEXTURE_2D
, GL_TEXTURE_MAG_FILTER
, GL_NEAREST
);
122 piglit_draw_rect_tex(-1, -1, 2, 2,
125 glDisable(GL_TEXTURE_2D
);
127 /* have to make up our own error measuring, since we
128 measure error on srgb side (so with values mapped back to srgb
129 using accurate formula) */
131 tolerance
= 0.5f
; /* as required by d3d10 */
132 glReadPixels(0, 0, 16, 16, GL_RGBA
, GL_FLOAT
, &readf
[0][0]);
134 for (i
= 0; i
< 256; i
++) {
135 float err
= fabs(piglit_linear_to_srgb(readf
[i
][0])*255 - (float)i
);
137 printf("readback: %f observed: %f expected: %f\n", readf
[i
][0],
138 piglit_linear_to_srgb(readf
[i
][0]), (float)i
);
142 if (err
> tolerance
) {
143 printf(" failed when testing srgb->float result\n");
148 printf("max error srgb->linear was %f\n", maxErr
);
150 piglit_present_results();
152 piglit_report_subtest_result(pass1
? PIGLIT_PASS
: PIGLIT_FAIL
,
155 /* draw into srgb framebuffer and verify results */
156 glBindTexture(GL_TEXTURE_2D
, texfb
);
157 glTexImage2D(GL_TEXTURE_2D
, 0, GL_SRGB8_ALPHA8_EXT
,
158 piglit_width
, piglit_height
, 0,
159 GL_RGBA
, GL_FLOAT
, NULL
);
161 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT
,
162 GL_COLOR_ATTACHMENT0_EXT
,
167 if (!piglit_check_gl_error(GL_NO_ERROR
))
168 piglit_report_result(PIGLIT_FAIL
);
170 glEnable(GL_FRAMEBUFFER_SRGB_EXT
);
171 status
= glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT
);
172 printf("Testing using fb srgb format");
173 if (status
!= GL_FRAMEBUFFER_COMPLETE_EXT
) {
174 printf(" - fbo incomplete (status = %s)\n",
175 piglit_get_gl_enum_name(status
));
176 piglit_report_subtest_result(PIGLIT_SKIP
, "srgb fb");
181 glEnable(GL_TEXTURE_2D
);
182 glBindTexture(GL_TEXTURE_2D
, texsrgb
);
183 piglit_draw_rect_tex(-1, -1, 2, 2,
185 glDisable(GL_TEXTURE_2D
);
187 tolerance
= 0.6f
; /* as required by d3d10 */
188 /* TODO: should test this tolerance too really right now only test
189 the previously converted from srgb values, so we only enforce
190 any value stays the same when doing srgb->linear->srgb, which
191 corresponds to 0.5 tolerance but only for these exact values. */
192 glReadPixels(0, 0, 16, 16, GL_RGBA
, GL_UNSIGNED_BYTE
, &readb
[0][0]);
194 for (i
= 0; i
< 256; i
++) {
196 printf("observed: %d expected: %d\n", readb
[i
][0], i
);
197 if (readb
[i
][0] != i
) {
198 printf(" failed when testing srgb->float->srgb result\n");
204 piglit_present_results();
206 piglit_report_subtest_result(pass2
? PIGLIT_PASS
: PIGLIT_FAIL
,
207 "srgb->linear->srgb");
209 glDeleteTextures(1, &texfb
);
210 glDeleteTextures(1, &texsrgb
);
211 glDeleteFramebuffersEXT(1, &fb
);
213 return (pass1
&& pass2
) ? PIGLIT_PASS
: PIGLIT_FAIL
;
216 enum piglit_result
piglit_display(void)
218 return test_format();
221 void piglit_init(int argc
, char **argv
)
223 piglit_require_extension("GL_EXT_framebuffer_object");
224 piglit_require_extension("GL_ARB_texture_env_combine");
225 piglit_require_extension("GL_EXT_texture_sRGB");
226 piglit_require_extension("GL_ARB_framebuffer_sRGB");
227 piglit_require_extension("GL_ARB_color_buffer_float");
228 glDisable(GL_DITHER
);