2 * Copyright © 2015 Intel Corporation
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
21 * DEALINGS IN THE SOFTWARE.
27 * Clears a multisample texture with various formats to various
28 * different colors and then samples from it in a shader to ensure
29 * that the expected color is returned. This includes verifying that
30 * when there are components missing they are overridden to the right
31 * value (such as GL_RED should report 0 for green and blue and 1 for
32 * the alpha). The main reason to do this is that the i965 driver has
33 * various different code paths to implement a fast clear optimisation
34 * and the path taken depends on the color chosen to a certain
37 * The test can take the following additional arguments:
39 * enable-fb-srgb: This will cause it to enable GL_FRAMEBUFFER_SRGB
40 * before clearing the buffer so that it can test that the color
41 * gets correctly converted to SRGB before being stored in the
43 * single-sample: A single sample texture will be created instead.
46 #include "piglit-util-gl.h"
47 #include "../../fbo/fbo-formats.h"
49 PIGLIT_GL_TEST_CONFIG_BEGIN
51 config
.supports_gl_compat_version
= 21;
52 config
.window_visual
= PIGLIT_GL_VISUAL_RGBA
| PIGLIT_GL_VISUAL_DOUBLE
;
53 config
.khr_no_error_support
= PIGLIT_NO_ERRORS
;
55 PIGLIT_GL_TEST_CONFIG_END
59 "attribute vec4 piglit_vertex;\n"
64 " gl_Position = piglit_vertex;\n"
68 fragment_source_float
[] =
77 " gl_FragColor = texelFetch(tex, ivec2(0), 0);\n"
81 fragment_source_int
[] =
90 " gl_FragColor = vec4(texelFetch(tex, ivec2(0), 0));\n"
94 fragment_source_uint
[] =
103 " gl_FragColor = vec4(texelFetch(tex, ivec2(0), 0));\n"
106 static const struct test_desc
*
107 test_set
= &test_sets
[0];
110 clear_colors
[][4] = {
111 { 0.0f
, 0.0f
, 0.0f
, 0.0f
},
112 { 1.0f
, 1.0f
, 1.0f
, 1.0f
},
113 { 0.0f
, 0.0f
, 1.0f
, 0.0f
},
114 { 1.0f
, 0.0f
, 0.0f
, 1.0f
},
116 { 0.25f
, 0.5f
, 0.75f
, 1.0f
},
117 { 0.75f
, 0.5f
, 0.25f
, 0.0f
},
118 { 0.5f
, 0.25f
, 0.75f
, 0.5f
},
120 { 2.0f
, 3.0f
, 0.5f
, 1.0f
},
121 { -2.0f
, 0.0f
, 0.25f
, 1.0f
},
122 { -0.5f
, 0.0f
, 0.25f
, 1.0f
},
125 struct component_sizes
{
132 static GLuint prog_float
, prog_int
, prog_uint
;
133 static GLuint result_fbo
;
134 static bool enable_fb_srgb
= false;
135 static bool single_sample
= false;
136 static int num_samples
= 2;
139 convert_srgb_color(const struct format_desc
*format
,
143 const char *format_name
= get_format_name(format
->internalformat
);
145 /* If the texture is not an sRGB format then no conversion is
146 * needed regardless of the sRGB settings.
148 if (strstr(format_name
, "SRGB") == NULL
&&
149 strstr(format_name
, "SLUMINANCE") == NULL
)
152 /* If GL_FRAMEBUFFER_SRGB was enabled when we did the clear
153 * then the clear color would have been converted to SRGB
154 * before being written. When it is sampled it will be
155 * converted back to linear. The two conversions cancel each
156 * other out so we don't need to do anything.
161 /* Otherwise we need to compensate for the color being
162 * converted to linear when sampled.
164 for (i
= 0; i
< 3; i
++)
165 color
[i
] = piglit_srgb_to_linear(color
[i
]);
169 clamp_signed(int value
, int size
)
173 (int) (UINT32_MAX
>> (33 - size
)));
177 clamp_unsigned(int value
, int size
)
181 return CLAMP((unsigned int) value
, 0, UINT32_MAX
>> (32 - size
));
184 static enum piglit_result
185 test_color(GLuint test_fbo
,
187 const struct format_desc
*format
,
189 const struct component_sizes
*sizes
,
190 const float *clear_color
)
192 float expected_color
[4];
195 glBindFramebuffer(GL_FRAMEBUFFER
, test_fbo
);
198 glEnable(GL_FRAMEBUFFER_SRGB
);
200 memcpy(expected_color
, clear_color
, sizeof expected_color
);
202 switch (clear_type
) {
204 GLint clear_color_int
[4];
205 for (i
= 0; i
< 4; i
++) {
206 expected_color
[i
] *= 127;
207 clear_color_int
[i
] = expected_color
[i
];
211 glUseProgram(prog_int
);
212 glClearBufferiv(GL_COLOR
,
217 case GL_UNSIGNED_INT
: {
218 GLuint clear_color_uint
[4];
219 for (i
= 0; i
< 4; i
++) {
220 expected_color
[i
] *= 255;
221 clear_color_uint
[i
] = MAX2(expected_color
[i
], 0);
225 glUseProgram(prog_uint
);
226 glClearBufferuiv(GL_COLOR
,
232 glUseProgram(prog_float
);
233 glClearColor(clear_color
[0],
237 glClear(GL_COLOR_BUFFER_BIT
);
242 glDisable(GL_FRAMEBUFFER_SRGB
);
244 switch (format
->base_internal_format
) {
246 expected_color
[0] = 0.0f
;
247 expected_color
[1] = 0.0f
;
248 expected_color
[2] = 0.0f
;
251 expected_color
[1] = expected_color
[0];
252 expected_color
[2] = expected_color
[0];
253 expected_color
[3] = expected_color
[0];
256 expected_color
[1] = expected_color
[0];
257 expected_color
[2] = expected_color
[0];
258 expected_color
[3] = 1.0f
;
260 case GL_LUMINANCE_ALPHA
:
261 expected_color
[1] = expected_color
[0];
262 expected_color
[2] = expected_color
[0];
265 expected_color
[1] = 0.0f
;
266 expected_color
[2] = 0.0f
;
267 expected_color
[3] = 1.0f
;
270 expected_color
[2] = 0.0f
;
271 expected_color
[3] = 1.0f
;
274 expected_color
[3] = 1.0f
;
278 convert_srgb_color(format
, expected_color
);
280 if (clear_type
== GL_UNSIGNED_NORMALIZED
) {
281 for (i
= 0; i
< 4; i
++) {
283 CLAMP(expected_color
[i
], 0.0f
, 1.0f
);
285 } else if (clear_type
== GL_SIGNED_NORMALIZED
) {
286 for (i
= 0; i
< 4; i
++) {
288 CLAMP(expected_color
[i
], -1.0f
, 1.0f
);
290 } else if (clear_type
== GL_INT
) {
291 /* The clear colors are multiplied by 127 for integer
292 * formats so some of them will be large values. The
293 * GL spec states that out-of-range integer values
294 * written to the framebuffer will be clamped so we
295 * need to replicate this in the expected values. For
296 * example, the -2.0 color will be set to -254, and
297 * this will be clamped to -128 for an 8-bit integer
300 expected_color
[0] = clamp_signed(expected_color
[0], sizes
->r
);
301 expected_color
[1] = clamp_signed(expected_color
[1], sizes
->g
);
302 expected_color
[2] = clamp_signed(expected_color
[2], sizes
->b
);
303 expected_color
[3] = clamp_signed(expected_color
[3], sizes
->a
);
304 } else if (clear_type
== GL_UNSIGNED_INT
) {
305 expected_color
[0] = clamp_unsigned(expected_color
[0], sizes
->r
);
306 expected_color
[1] = clamp_unsigned(expected_color
[1], sizes
->g
);
307 expected_color
[2] = clamp_unsigned(expected_color
[2], sizes
->b
);
308 expected_color
[3] = clamp_unsigned(expected_color
[3], sizes
->a
);
309 } else if (test_sets
[test_index
].format
== ext_packed_float
) {
310 /* These formats can't store negative values */
311 for (i
= 0; i
< 4; i
++)
312 expected_color
[i
] = MAX2(expected_color
[i
], 0.0f
);
315 /* Display something on the winsys FBO just so that something
316 * will be shown. This isn't used for the test results because
317 * the winsys buffer is a normalised format and some of the
318 * values we want to detect will be out of the range [0,1].
320 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
321 piglit_draw_rect(offset
* 16 * 2.0f
/ piglit_width
- 1.0f
,
323 16 * 2.0f
/ piglit_width
,
324 16 * 2.0f
/ piglit_height
);
326 glBindFramebuffer(GL_FRAMEBUFFER
, result_fbo
);
327 piglit_draw_rect(-1, -1, 2, 2);
329 return piglit_probe_rect_rgba(0, 0, 1, 1, expected_color
) ?
334 static enum piglit_result
335 test_format(const struct format_desc
*format
)
337 enum piglit_result result
= PIGLIT_PASS
;
338 enum piglit_result color_result
;
339 struct component_sizes sizes
;
347 const char *name
= get_format_name(format
->internalformat
);
349 if (format
->internalformat
== 3 || format
->internalformat
== 4)
352 /* Compressed formats aren't supported for multisampling */
353 if (strstr("COMPRESSED", name
))
356 printf("Testing %s\n", name
);
359 tex_target
= GL_TEXTURE_2D
;
361 tex_target
= GL_TEXTURE_2D_MULTISAMPLE
;
363 glGenTextures(1, &tex
);
364 glBindTexture(tex_target
, tex
);
367 glTexParameteri(tex_target
,
368 GL_TEXTURE_MAG_FILTER
,
370 glTexParameteri(tex_target
,
371 GL_TEXTURE_MIN_FILTER
,
373 glTexParameteri(tex_target
,
374 GL_TEXTURE_MAX_LEVEL
,
376 /* The pitch of the texture needs to at least as wide
377 * as a tile and taller than 1 pixel so that it will
378 * be y-tiled in the i965 driver. Otherwise fast
379 * clears will be disabled and the test will be
382 glTexImage2D(tex_target
,
384 format
->internalformat
,
385 128, 128, /* width/height */
387 GL_RGBA
, GL_UNSIGNED_BYTE
,
390 if (piglit_khr_no_error
)
393 piglit_reset_gl_error();
395 /* The size doesn't matter on the i965 driver for
396 * multisample surfaces because it will always
397 * allocate an MCS buffer and so it will always do
400 glTexImage2DMultisample(tex_target
,
402 format
->internalformat
,
403 1, 1, /* width/height */
404 GL_FALSE
/* fixed sample locations */);
405 tex_error
= glGetError();
407 if (tex_error
!= GL_NO_ERROR
) {
408 glDeleteTextures(1, &tex
);
410 if (tex_error
== GL_INVALID_ENUM
) {
411 /* You're only supposed to pass color
412 * renderable formats to
413 * glTexImage2DMultisample.
415 printf("Format is not color renderable\n");
418 printf("Unexpected GL error: %s 0x%x\n",
419 piglit_get_gl_error_name(tex_error
),
426 glGetTexLevelParameteriv(tex_target
, 0,
427 GL_TEXTURE_LUMINANCE_SIZE
, &sizes
.l
);
428 glGetTexLevelParameteriv(tex_target
, 0,
429 GL_TEXTURE_ALPHA_SIZE
, &sizes
.a
);
430 glGetTexLevelParameteriv(tex_target
, 0,
431 GL_TEXTURE_INTENSITY_SIZE
, &sizes
.i
);
432 glGetTexLevelParameteriv(tex_target
, 0,
433 GL_TEXTURE_RED_SIZE
, &sizes
.r
);
434 glGetTexLevelParameteriv(tex_target
, 0,
435 GL_TEXTURE_GREEN_SIZE
, &sizes
.g
);
436 glGetTexLevelParameteriv(tex_target
, 0,
437 GL_TEXTURE_BLUE_SIZE
, &sizes
.b
);
440 type_param
= GL_TEXTURE_LUMINANCE_TYPE
;
441 else if (sizes
.i
> 0)
442 type_param
= GL_TEXTURE_INTENSITY_TYPE
;
443 else if (sizes
.r
> 0)
444 type_param
= GL_TEXTURE_RED_TYPE
;
445 else if (sizes
.a
> 0)
446 type_param
= GL_TEXTURE_ALPHA_TYPE
;
449 type_param
= GL_NONE
;
451 glGetTexLevelParameteriv(tex_target
,
456 switch (format
->base_internal_format
) {
458 sizes
.r
= sizes
.g
= sizes
.b
= 8;
461 sizes
.r
= sizes
.g
= sizes
.b
= sizes
.a
= sizes
.i
;
464 sizes
.r
= sizes
.g
= sizes
.b
= sizes
.l
;
467 case GL_LUMINANCE_ALPHA
:
468 sizes
.r
= sizes
.g
= sizes
.b
= sizes
.l
;
471 sizes
.g
= sizes
.b
= sizes
.a
= 8;
474 sizes
.b
= sizes
.a
= 8;
481 piglit_set_tolerance_for_bits(sizes
.r
, sizes
.g
, sizes
.b
, sizes
.a
);
483 glGenFramebuffers(1, &fbo
);
484 glBindFramebuffer(GL_FRAMEBUFFER
, fbo
);
485 glFramebufferTexture2D(GL_FRAMEBUFFER
,
486 GL_COLOR_ATTACHMENT0
,
490 if (glCheckFramebufferStatus(GL_FRAMEBUFFER
) ==
491 GL_FRAMEBUFFER_COMPLETE
) {
492 for (i
= 0; i
< ARRAY_SIZE(clear_colors
); i
++) {
493 color_result
= test_color(fbo
, i
, format
, type
, &sizes
,
495 if (color_result
== PIGLIT_SKIP
) {
496 if (result
== PIGLIT_PASS
)
497 result
= PIGLIT_SKIP
;
499 } else if (color_result
== PIGLIT_FAIL
) {
500 result
= PIGLIT_FAIL
;
504 printf("FBO not complete\n");
505 result
= PIGLIT_SKIP
;
508 glDeleteFramebuffers(1, &fbo
);
509 glDeleteTextures(1, &tex
);
517 return fbo_formats_display(test_format
);
521 build_program(const char *fragment_source
)
527 (void)!asprintf(&source
,
531 "#extension GL_ARB_texture_multisample : require\n",
532 single_sample
? "sampler2D" : "sampler2DMS");
534 prog
= piglit_build_simple_program(vertex_source
, source
);
539 tex_location
= glGetUniformLocation(prog
, "tex");
540 glUniform1i(tex_location
, 0);
546 piglit_init(int argc
, char **argv
)
548 int test_set_index
= 0;
552 for (i
= 1; i
< argc
; i
++) {
553 if (!strcmp(argv
[i
], "enable-fb-srgb")) {
554 enable_fb_srgb
= true;
555 piglit_require_extension("GL_ARB_framebuffer_sRGB");
556 } else if (!strcmp(argv
[i
], "single-sample")) {
557 single_sample
= true;
559 test_set_index
= fbo_lookup_test_set(argv
[i
]);
563 if (!single_sample
) {
564 piglit_require_extension("GL_ARB_texture_multisample");
565 /* Use the max number of samples for testing */
566 glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES
, &num_samples
);
567 printf("Testing %d samples\n", num_samples
);
570 piglit_require_extension("GL_ARB_texture_float");
571 piglit_require_GLSL_version(130);
573 test_set
= test_set
+ test_set_index
;
575 fbo_formats_init_test_set(test_set_index
,
576 GL_TRUE
/* print_options */);
578 /* Create a floating point fbo to store the result of
579 * sampling. It is only used to store a single color sampled
580 * from the texture so it doesn't need to bigger than 1x1.
582 glGenFramebuffers(1, &result_fbo
);
583 glBindFramebuffer(GL_FRAMEBUFFER
, result_fbo
);
584 glGenRenderbuffers(1, &rb
);
585 glBindRenderbuffer(GL_RENDERBUFFER
, rb
);
586 glRenderbufferStorage(GL_RENDERBUFFER
,
588 1, 1 /* width/height */);
589 glFramebufferRenderbuffer(GL_FRAMEBUFFER
,
590 GL_COLOR_ATTACHMENT0
,
593 if (glCheckFramebufferStatus(GL_FRAMEBUFFER
) !=
594 GL_FRAMEBUFFER_COMPLETE
) {
595 printf("Couldn't create RGBA32F FBO\n");
596 piglit_report_result(PIGLIT_SKIP
);
598 glBindFramebuffer(GL_FRAMEBUFFER
, piglit_winsys_fbo
);
600 prog_float
= build_program(fragment_source_float
);
601 prog_int
= build_program(fragment_source_int
);
602 prog_uint
= build_program(fragment_source_uint
);