glsl: test loop unroll with uint overflow
[piglit.git] / tests / spec / ext_framebuffer_multisample / draw-buffers-common.cpp
blob48e1ad4a547442c81be4732a9a7319c6797a38b3
1 /*
2 * Copyright © 2012 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
13 * Software.
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
21 * IN THE SOFTWARE.
24 #include "draw-buffers-common.h"
25 using namespace piglit_util_fbo;
27 /**
28 * \file draw-buffers-common.cpp
30 * This file provides utility functions to draw a test pattern to multiple draw
31 * buffers attached to a FBO with GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE}
32 * enabled / disabled.
34 * Expected color values are computed for each draw buffer based on the enabled
35 * GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE} flags and coverage value used to draw the
36 * test pattern.
38 * Reference image for each draw buffer is drawn in to right half of default
39 * framebuffer. It is used to verify the accuracy of test image as well as to
40 * visually compare the difference caused by enabling above flags.
42 * Test image is drawn with the same test pattern in multisample buffer with
43 * GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE} enabled. All multisample draw buffers
44 * are sequentially resolved by blitting them to a single sample FBO. resolve_fbo
45 * is then blitted to left half of window system framebuffer with appropriate y
46 * offset. This produces three test images in the left half, each corresponds to
47 * a color attachment.
49 * Test image is verified by comparing it with the corresponding reference
50 * image in the right half
52 * For sample coverage and sample alpha to coverage, test image should be
53 * verified by probing the rectangles in left half of window system framebuffer
54 * and comparing with expected color values. OpenGL 3.0 specification intends to
55 * allow (but not require) the implementation to produce a dithering effect when
56 * the coverage value is not a strict multiple of 1 / num_samples. We will skip
57 * computing expected values and probing for such rectangles. They are drawn
58 * just to look for dithering by human inspection.
60 * Note:
61 * At present, the test always uses three draw buffers. To test other
62 * numbers of draw buffers, we would have to modify the fragment shader in
63 * nontrivial ways at run time.
65 * Also, the test always uses GL_RGBA8I as integer format or GL_RGBA as float
66 * format for draw buffer zero.
68 * Author: Anuj Phogat <anuj.phogat@gmail.com>
71 static Fbo ms_fbo, resolve_fbo, resolve_int_fbo;
72 static GLbitfield buffer_to_test;
74 static float *coverage = NULL;
75 static float *color = NULL;
76 static float *depth = NULL;
77 static float *expected_color = NULL;
78 static float *expected_depth = NULL;
80 static int num_draw_buffers;
81 static int num_samples;
82 static int num_rects;
83 static int prog;
84 static int color_loc;
85 static int depth_loc;
86 static int frag_0_color_loc;
87 static int alpha_to_coverage_loc;
88 static int pattern_width;
89 static int pattern_height;
91 static bool is_buffer_zero_integer_format = false;
92 static bool is_dual_src_blending = false;
93 static GLenum draw_buffer_zero_format;
95 static const int num_components = 4; /* for RGBA formats */
96 static const int num_color_bits = 8; /* for GL_RGBA & GL_RGBA8I formats */
98 static const float bg_depth = 0.8;
99 static const float bg_color[4] = {
100 0.0, 0.6, 0.0, 0.4 };
102 /* Testing for three draw buffers is supported */
103 static const GLenum draw_buffers[] = {
104 GL_COLOR_ATTACHMENT0_EXT,
105 GL_COLOR_ATTACHMENT1_EXT,
106 GL_COLOR_ATTACHMENT2_EXT };
108 /* Offset the viewport transformation on depth value passed to the vertex
109 * shader by setting it to (2 * depth - 1.0).
111 static const char *vert_template =
112 "#version %s\n"
113 "attribute vec2 pos;\n"
114 "uniform float depth;\n"
115 "void main()\n"
116 "{\n"
117 " vec4 eye_pos = gl_ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);\n"
118 " gl_Position = vec4(eye_pos.xy, 2 * depth - 1.0, 1.0);\n"
119 "}\n";
121 /* Fragment shader generates three different color outputs. Different color
122 * values are generated based on if sample_alpha_to_coverage / dual_src_blend
123 * are enabled or not.
125 static const char *frag_template =
126 "#version %s\n"
127 "#define NUM_ATTACHMENTS %d\n"
128 "#define DUAL_SRC_BLEND %d\n"
129 "#define ALPHA_TO_COVERAGE %d\n"
130 "#define OUT_TYPE %s\n"
131 "#define FRAG_OUT_ZERO_WRITE %d\n"
132 "#if __VERSION__ == 130\n"
133 "out OUT_TYPE frag_out_0;\n"
134 "#if DUAL_SRC_BLEND\n"
135 "out vec4 frag_out_1;\n"
136 "#elif NUM_ATTACHMENTS > 1\n"
137 "out vec4 frag_out_1;\n"
138 "out vec4 frag_out_2;\n"
139 "#endif\n"
140 "#else\n"
141 "#define frag_out_0 gl_FragData[0]\n"
142 "#if NUM_ATTACHMENTS > 1\n"
143 "#define frag_out_1 gl_FragData[1]\n"
144 "#define frag_out_2 gl_FragData[2]\n"
145 "#endif\n"
146 "#endif\n"
147 "uniform OUT_TYPE frag_0_color;\n"
148 "uniform vec4 color;\n"
149 "void main()\n"
150 "{\n"
151 " #if FRAG_OUT_ZERO_WRITE\n"
152 " frag_out_0 = frag_0_color;\n"
153 " #endif\n"
154 " #if DUAL_SRC_BLEND\n"
155 " frag_out_1 = vec4(color.rgb, 1.0 - color.a / 2.0);\n"
156 " #elif ALPHA_TO_COVERAGE && NUM_ATTACHMENTS > 1\n"
157 " frag_out_1 = vec4(color.rgb, color.a / 2);\n"
158 " frag_out_2 = vec4(color.rgb, color.a / 4);\n"
159 " #elif NUM_ATTACHMENTS > 1\n"
160 " frag_out_1 = frag_out_2 = color;\n"
161 " #endif\n"
162 "}\n";
164 const char *
165 get_out_type_glsl(void)
167 if (is_buffer_zero_integer_format)
168 return "ivec4";
169 else
170 return "vec4";
172 void
173 shader_compile(bool sample_alpha_to_coverage,
174 bool dual_src_blend,
175 bool frag_out_zero_write)
177 bool need_glsl130 = is_buffer_zero_integer_format || dual_src_blend;
179 if (need_glsl130) {
180 piglit_require_gl_version(30);
183 is_dual_src_blending = dual_src_blend;
185 /* Compile program */
186 unsigned vert_alloc_len = strlen(vert_template) + 4;
187 char *vert = (char *) malloc(vert_alloc_len);
188 sprintf(vert, vert_template, need_glsl130 ? "130" : "120");
189 GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);
190 free(vert);
192 /* Generate appropriate fragment shader program */
193 const char *out_type_glsl = get_out_type_glsl();
194 unsigned frag_alloc_len = strlen(frag_template) +
195 strlen(out_type_glsl) + 4;
196 char *frag = (char *) malloc(frag_alloc_len);
197 sprintf(frag, frag_template, need_glsl130 ? "130" : "120",
198 num_draw_buffers,
199 is_dual_src_blending,
200 sample_alpha_to_coverage,
201 out_type_glsl,
202 frag_out_zero_write);
204 GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);
205 prog = piglit_link_simple_program(vs, fs);
207 if (!piglit_link_check_status(prog)) {
208 piglit_report_result(PIGLIT_FAIL);
210 free(frag);
212 if (need_glsl130) {
213 if (is_dual_src_blending) {
214 glBindFragDataLocationIndexed(prog, 0, 0, "frag_out_0");
215 glBindFragDataLocationIndexed(prog, 0, 1, "frag_out_1");
218 else if (num_draw_buffers > 1) {
219 glBindFragDataLocation(prog, 0, "frag_out_0");
220 glBindFragDataLocation(prog, 1, "frag_out_1");
221 glBindFragDataLocation(prog, 2, "frag_out_2");
223 else
224 glBindFragDataLocation(prog, 0, "frag_out_0");
227 glBindAttribLocation(prog, 0, "pos");
228 glEnableVertexAttribArray(0);
230 /* Linking is required after glBindFragDataLocation */
231 glLinkProgram(prog);
233 /* Set up uniforms */
234 glUseProgram(prog);
235 color_loc = glGetUniformLocation(prog, "color");
236 depth_loc = glGetUniformLocation(prog, "depth");
237 frag_0_color_loc = glGetUniformLocation(prog, "frag_0_color");
238 alpha_to_coverage_loc = glGetUniformLocation(prog, "alphatocoverage");
241 void
242 allocate_data_arrays(void)
244 float alpha_scale;
245 /* Draw 2N + 1 rectangles for N samples, each with a unique color
246 * and coverage value
248 if (num_samples) {
249 num_rects = 2 * num_samples + 1;
250 alpha_scale = (1.0 / (2.0 * num_samples));
252 else {
253 num_rects = 9;
254 alpha_scale = 0.125;
257 /* Allocate data arrays based on number of samples used */
258 color = (float *) malloc(num_rects *
259 num_components *
260 sizeof(float));
261 expected_color = (float *) malloc(num_draw_buffers *
262 num_rects *
263 num_components *
264 sizeof(float));
265 depth = (float *) malloc(num_rects * sizeof(float));
266 expected_depth = (float *) malloc(num_draw_buffers *
267 num_rects *
268 sizeof(float));
269 coverage = (float *) malloc(num_rects * sizeof(float));
271 for (int i = 0; i < num_rects; i++) {
272 unsigned rect_idx = i * num_components;
273 for (int j = 0; j < num_components - 1; j++) {
274 color[rect_idx + j] =
275 (sin((float)(rect_idx + j)) + 1) / 2;
278 /* In case of alpha-to-coverage enabled, alpha values will be
279 * directly used as coverage.
281 if (buffer_to_test == GL_DEPTH_BUFFER_BIT)
282 /* For depth buffer testing with alpha-to-coverage,
283 * set more rects with alpha = 1.0.
285 color[rect_idx + 3] = 2 * i * alpha_scale;
286 else
287 color[rect_idx + 3] = i * alpha_scale;
289 depth[i] = i * (alpha_scale / 2.0);
293 void
294 free_data_arrays(void)
296 free(color);
297 color = NULL;
298 free(depth);
299 depth = NULL;
300 free(coverage);
301 coverage = NULL;
302 free(expected_color);
303 expected_color = NULL;
306 void
307 float_color_to_int_color(int *dst, float *src)
309 float offset = 1 - (1 << (num_color_bits - 1));
310 float scale = -2.0 * offset;
312 for (int j = 0; j < num_rects; ++j) {
313 for (int k = 0; k < num_components; ++k) {
314 dst[j * num_components + k] =
315 scale * src[j * num_components + k] + offset;
320 void
321 draw_pattern(bool sample_alpha_to_coverage,
322 bool sample_alpha_to_one,
323 bool is_reference_image,
324 float *float_color)
326 glUseProgram(prog);
327 if (buffer_to_test == GL_COLOR_BUFFER_BIT)
328 glClearColor(bg_color[0], bg_color[1],
329 bg_color[2], bg_color[3]);
330 else if (buffer_to_test == GL_DEPTH_BUFFER_BIT)
331 glClearDepth(bg_depth);
332 glClear(buffer_to_test);
334 if (!is_reference_image) {
335 if (sample_alpha_to_coverage)
336 glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
337 if (sample_alpha_to_one)
338 glEnable(GL_SAMPLE_ALPHA_TO_ONE);
340 glUniform1i(alpha_to_coverage_loc, sample_alpha_to_coverage);
342 unsigned indices[6] = {0, 1, 2, 0, 2, 3};
343 int *integer_color = (int *) malloc(num_rects *
344 num_components *
345 sizeof(int));
347 /* For integer color buffers convert the color data to integer format */
348 if (is_buffer_zero_integer_format) {
349 float_color_to_int_color(integer_color, float_color);
352 for (int i = 0; i < num_rects; ++i) {
353 float vertices[4][2] = {
354 { 0.0f, 0.0f + i * (pattern_height / num_rects) },
355 { 0.0f, (i + 1.0f) * (pattern_height / num_rects) },
356 { pattern_width, (i + 1.0f) * (pattern_height / num_rects) },
357 { pattern_width, 0.0f + i * (pattern_height / num_rects) } };
359 glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,
360 sizeof(vertices[0]),
361 (void *) vertices);
363 glUniform4fv(color_loc, 1, (float_color + i * num_components));
364 if (is_buffer_zero_integer_format) {
365 glUniform4iv(frag_0_color_loc, 1,
366 integer_color + i * num_components);
368 else {
369 glUniform4fv(frag_0_color_loc, 1,
370 (float_color + i * num_components));
372 glUniform1f(depth_loc, depth[i]);
373 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,
374 (void *) indices);
376 glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
377 glDisable(GL_SAMPLE_ALPHA_TO_ONE);
378 free(integer_color);
381 float
382 get_alpha_blend_factor(float src0_alpha, float src1_alpha,
383 bool compute_src)
385 GLint blend_func;
386 if (compute_src)
387 glGetIntegerv(GL_BLEND_SRC_RGB, &blend_func);
388 else
389 glGetIntegerv(GL_BLEND_DST_RGB, &blend_func);
391 switch(blend_func) {
392 case GL_SRC_ALPHA:
393 return src0_alpha;
394 break;
395 case GL_ONE_MINUS_SRC_ALPHA:
396 return (1.0 - src0_alpha);
397 break;
398 case GL_SRC1_ALPHA:
399 return src1_alpha;
400 break;
401 case GL_ONE_MINUS_SRC1_ALPHA:
402 return (1.0 - src1_alpha);
403 break;
404 default:
405 printf("Blend function is not supported"
406 " by test case\n");
408 return -1;
411 void
412 compute_blend_color(float *frag_color, int rect_count,
413 bool sample_alpha_to_one)
415 float src_blend_factor, dst_blend_factor;
416 /* Taking in to account alpha values output by
417 * fragment shader.
419 float src0_alpha = color[rect_count * num_components + 3];
420 float src1_alpha = 1.0 - src0_alpha / 2.0;
422 if (sample_alpha_to_one && num_samples) {
423 /* Set fragment src0_alpha, src1_alpha to 1.0 and use them
424 * to compute blending factors.
426 src0_alpha = 1.0;
427 src1_alpha = 1.0;
430 src_blend_factor = get_alpha_blend_factor(src0_alpha,
431 src1_alpha,
432 true);
433 dst_blend_factor = get_alpha_blend_factor(src0_alpha,
434 src1_alpha,
435 false);
436 /* Using default BlendEquation, blend_color is:
437 * src0_color * src_blend_factor + dst_color * dst_blend_factor
439 for (int j = 0; j < num_components; j++) {
440 float blend_color=
441 color[rect_count * num_components + j] *
442 src_blend_factor +
443 bg_color[j] *
444 dst_blend_factor;
446 frag_color[rect_count * num_components + j] =
447 (blend_color > 1) ? 1.0 : blend_color;
451 void
452 compute_expected_color(bool sample_alpha_to_coverage,
453 bool sample_alpha_to_one,
454 int draw_buffer_count)
456 unsigned buffer_idx_offset = draw_buffer_count *
457 num_rects *
458 num_components;
459 for (int i = 0; i < num_rects; i++) {
461 float *frag_color = NULL;
462 float samples_used = coverage[i] * num_samples;
463 /* Expected color values are computed only for integer
464 * number of samples_used. Non-integer values may result
465 * in dithering effect.
467 if (samples_used == (int) samples_used) {
468 int rect_idx_offset = buffer_idx_offset +
469 i * num_components;
470 frag_color = (float *) malloc(num_rects *
471 num_components *
472 sizeof(float));
474 /* Do dual source blending computations */
475 if (is_dual_src_blending) {
476 compute_blend_color(frag_color,
477 i /* rect_count */,
478 sample_alpha_to_one);
480 else {
481 memcpy(frag_color, color,
482 num_rects * num_components *
483 sizeof(float));
486 /* Coverage value decides the number of samples in
487 * multisample buffer covered by an incoming fragment,
488 * which will then receive the fragment data. When the
489 * multisample buffer is resolved it gets blended with
490 * the background color which is written to the
491 * remaining samples. Page 254 (page 270 of the PDF) of
492 * the OpenGL 3.0 spec says: "The method of combination
493 * is not specified, though a simple average computed
494 * independently for each color component is recommended."
495 * This is followed by NVIDIA and AMD in their proprietary
496 * linux drivers.
498 for (int j = 0; j < num_components - 1 ; j++) {
500 expected_color[rect_idx_offset + j] =
501 frag_color[i * num_components + j] * coverage[i] +
502 bg_color[j] * (1 - coverage[i]);
505 /* Compute expected alpha values of draw buffers */
506 float frag_alpha = frag_color[i * num_components + 3];
507 int alpha_idx = rect_idx_offset + 3;
509 if ((!num_samples &&
510 !sample_alpha_to_coverage) ||
511 is_buffer_zero_integer_format) {
512 /* Taking in to account alpha values output by
513 * fragment shader.
515 expected_color[alpha_idx] =
516 is_buffer_zero_integer_format ?
517 frag_alpha / (1 << draw_buffer_count) :
518 frag_alpha;
520 else if (sample_alpha_to_coverage) {
521 /* Taking in to account alpha values output by
522 * fragment shader.
524 frag_alpha /= (1 << draw_buffer_count);
525 if (sample_alpha_to_one) {
526 expected_color[alpha_idx] =
527 1.0 * coverage[i] +
528 bg_color[3] * (1 - coverage[i]);
530 else {
531 expected_color[alpha_idx] =
532 frag_alpha * coverage[i] +
533 bg_color[3] * (1 - coverage[i]);
536 else {
537 expected_color[alpha_idx] =
538 sample_alpha_to_one ? 1.0 : frag_alpha;
541 free(frag_color);
546 void
547 compute_expected_depth(void)
549 /* Compute the expected depth values only for coverage value equal to
550 * 0.0 and 1.0. Expected depth is not defined by OpenGL specification
551 * when coverage value is between 0.0 and 1.0 */
552 for (int i = 0; i < num_rects; i++) {
553 if (coverage[i] == 0.0)
554 expected_depth[i] = bg_depth;
555 else if (coverage[i] == 1.0)
556 expected_depth[i] = (depth[i] < 1.0) ? depth[i] : 1.0;
560 void
561 compute_expected(bool sample_alpha_to_coverage,
562 bool sample_alpha_to_one,
563 int draw_buffer_count)
565 int i;
566 /* Compute the coverage value used in the test */
567 if (num_samples &&
568 sample_alpha_to_coverage &&
569 !is_buffer_zero_integer_format) {
571 for (i = 0; i < num_rects; i++) {
572 /* Coverage value for all the draw buffers comes from
573 * the fragment alpha values of draw buffer zero
575 float frag_alpha = color[i * num_components + 3];
576 coverage[i] = (frag_alpha < 1.0) ? frag_alpha : 1.0;
579 else {
580 for (i = 0; i < num_rects; i++)
581 coverage[i] = 1.0;
584 if (buffer_to_test == GL_COLOR_BUFFER_BIT) {
585 /* Don't compute expected color for color buffer zero
586 * if no renderbuffer is attached to it.
588 if (draw_buffer_count == 0 && draw_buffer_zero_format == GL_NONE)
589 return;
590 compute_expected_color(sample_alpha_to_coverage,
591 sample_alpha_to_one,
592 draw_buffer_count);
594 else if (buffer_to_test == GL_DEPTH_BUFFER_BIT)
595 compute_expected_depth();
599 /* This function probes all the draw buffers blitted to downsampled FBO
600 * (resolve_fbo / resolve_int_fbo) and compare against expected color values.
602 bool
603 probe_framebuffer_color(void)
605 bool result = true;
606 int * expected_int_color = NULL;
607 int rect_width = pattern_width;
608 int rect_height = pattern_height / num_rects;
610 for (int i = 0; i < num_draw_buffers; i++) {
611 /* Don't probe color buffer zero if no renderbuffer is
612 * attached to it.
614 if (i == 0 && draw_buffer_zero_format == GL_NONE)
615 continue;
616 bool is_integer_operation = is_buffer_zero_integer_format && !i;
618 if (is_integer_operation) {
619 glBindFramebuffer(GL_READ_FRAMEBUFFER,
620 resolve_int_fbo.handle);
621 expected_int_color = (int*) malloc(num_rects *
622 num_components *
623 sizeof(int));
625 else {
626 glBindFramebuffer(GL_READ_FRAMEBUFFER,
627 resolve_fbo.handle);
630 for (int j = 0; j < num_rects; j++) {
631 float samples_used = coverage[j] * num_samples;
632 int rect_x = 0;
633 int rect_y = i * pattern_height +
634 j * rect_height;
635 int rect_idx_offset = (i * num_rects + j) *
636 num_components;
638 /* Only probe rectangles with coverage value which is a
639 * strict multiple of 1 / num_samples.
641 if (samples_used == (int)samples_used) {
642 if (is_integer_operation) {
643 float_color_to_int_color(expected_int_color,
644 expected_color);
645 result = piglit_probe_rect_rgba_int(
646 rect_x,
647 rect_y,
648 rect_width,
649 rect_height,
650 expected_int_color +
651 rect_idx_offset)
652 && result;
654 else {
655 result = piglit_probe_rect_rgba(
656 rect_x,
657 rect_y,
658 rect_width,
659 rect_height,
660 expected_color + rect_idx_offset)
661 && result;
666 if (expected_int_color)
667 free(expected_int_color);
668 return result;
671 bool
672 probe_framebuffer_depth(void)
674 bool result = true;
675 int rect_width = pattern_width;
676 int rect_height = pattern_height / num_rects;
678 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo.handle);
679 for (int i = 0; i < num_rects; i++) {
680 if (coverage[i] == 0.0 || coverage[i] == 1.0) {
681 int rect_x = 0;
682 int rect_y = i * rect_height;
683 int rect_idx = i;
685 result = piglit_probe_rect_depth(
686 rect_x,
687 rect_y,
688 rect_width,
689 rect_height,
690 expected_depth[rect_idx])
691 && result;
693 else {
694 /*Skip probing polygons which are drawn with fractional
695 * coverage value (between 0.0 and 1.0)*/
696 continue;
699 return result;
702 void
703 draw_image_to_window_system_fb(int draw_buffer_count, bool rhs)
705 unsigned rect_x = 0;
706 unsigned rect_y = draw_buffer_count * pattern_height;
707 unsigned array_size = num_components * pattern_width * pattern_height;
708 float *image = (float *) malloc(sizeof(float) * array_size);
710 if (is_buffer_zero_integer_format && draw_buffer_count == 0) {
711 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_int_fbo.handle);
712 int *tmp = (int *) malloc(sizeof(int) * array_size);
713 glReadPixels(rect_x, rect_y,
714 pattern_width, pattern_height,
715 GL_RGBA_INTEGER,
716 GL_INT, tmp);
717 for (unsigned i = 0; i < array_size; ++i) {
718 image[i] = tmp[i];
721 /* Convert integer color data to float color data */
722 float color_offset = 1.0 - (1 << (num_color_bits - 1));
723 float color_scale = -2.0 * color_offset;
725 for (unsigned i = 0; i < array_size; ++i) {
726 image[i] = (image[i] - color_offset) / color_scale;
728 free(tmp);
730 else{
731 glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo.handle);
732 glReadPixels(rect_x, rect_y,
733 pattern_width,
734 pattern_height,
735 GL_RGBA,
736 GL_FLOAT, image);
739 /* Rendering using gldrawPixels() with dual source blending enabled
740 * produces undefined results. So, disable blending in
741 * piglit_visualize_image function to avoid undefined behavior.
743 GLboolean isBlending;
744 glGetBooleanv(GL_BLEND, &isBlending);
745 glDisable(GL_BLEND);
746 piglit_visualize_image(image, GL_RGBA,
747 pattern_width, pattern_height,
748 draw_buffer_count + 1, rhs);
749 if (isBlending)
750 glEnable(GL_BLEND);
751 free(image);
754 void
755 draw_test_image(bool sample_alpha_to_coverage, bool sample_alpha_to_one)
757 /* Draw test pattern in multisample ms_fbo with
758 * GL_SAMPLE_ALPHA_TO_COVERAGE enabled
760 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
761 glDrawBuffers(num_draw_buffers, draw_buffers);
762 ms_fbo.set_viewport();
764 draw_pattern(sample_alpha_to_coverage,
765 sample_alpha_to_one,
766 false /* is_reference_image */,
767 color);
769 for (int i = 0; i < num_draw_buffers; i++) {
771 /* Blit ms_fbo to singlesample FBO to resolve multisample
772 * buffer.
774 glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);
775 if (buffer_to_test == GL_COLOR_BUFFER_BIT)
776 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i);
778 if (is_buffer_zero_integer_format && !i)
779 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
780 resolve_int_fbo.handle);
781 else
782 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
783 resolve_fbo.handle);
785 /* Blit all the draw buffers to resolve_fbo / resolve_int_fbo
786 * with different y_offset.
788 unsigned y_offset = i * pattern_height;
789 glBlitFramebuffer(0, 0,
790 pattern_width, pattern_height,
791 0, y_offset,
792 pattern_width, pattern_height + y_offset,
793 buffer_to_test, GL_NEAREST);
795 if (buffer_to_test == GL_COLOR_BUFFER_BIT) {
796 draw_image_to_window_system_fb(i /* draw_buffer_count */,
797 false /* rhs */);
800 /* Expected color values for all the draw buffers are computed
801 * to aid probe_framebuffer_color() and probe_framebuffer_depth()
802 * in verification.
804 if (sample_alpha_to_coverage || is_dual_src_blending) {
805 /* Expected color is different for different draw
806 * buffers
808 compute_expected(sample_alpha_to_coverage,
809 sample_alpha_to_one,
810 i /* draw_buffer_count */);
815 void
816 draw_reference_image(bool sample_alpha_to_coverage, bool sample_alpha_to_one)
818 /* Draw test pattern in multisample ms_fbo with
819 * GL_SAMPLE_ALPHA_TO_COVERAGE disabled.
821 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
822 glDrawBuffers(num_draw_buffers, draw_buffers);
823 ms_fbo.set_viewport();
825 if (sample_alpha_to_coverage) {
826 draw_pattern(sample_alpha_to_coverage,
827 sample_alpha_to_one,
828 true /* is_reference_image */,
829 color);
831 else {
832 /* Value of draw_buffer_count doesn't matter in this case */
833 compute_expected(sample_alpha_to_coverage,
834 sample_alpha_to_one,
835 0 /* draw_buffer_count */);
836 draw_pattern(sample_alpha_to_coverage,
837 sample_alpha_to_one,
838 true /* is_reference_image */,
839 expected_color);
842 for (int i = 0; i < num_draw_buffers; i++) {
844 /* Blit ms_fbo to resolve_fbo to resolve multisample buffer */
845 glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);
846 if (buffer_to_test == GL_COLOR_BUFFER_BIT)
847 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i);
848 if (is_buffer_zero_integer_format && !i) {
849 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
850 resolve_int_fbo.handle);
852 else {
853 glBindFramebuffer(GL_DRAW_FRAMEBUFFER,
854 resolve_fbo.handle);
857 /* Blit all the draw buffers to resolve_fbo with different
858 * y_offset.
860 unsigned y_offset = i * pattern_height;
861 glBlitFramebuffer(0, 0,
862 pattern_width, pattern_height,
863 0, y_offset,
864 pattern_width, pattern_height + y_offset,
865 buffer_to_test, GL_NEAREST);
867 if (buffer_to_test == GL_COLOR_BUFFER_BIT) {
868 draw_image_to_window_system_fb(i /* draw_buffer_count */,
869 true /* rhs */);
874 void
875 ms_fbo_and_draw_buffers_setup(int samples,
876 int width,
877 int height,
878 int n_attachments,
879 GLenum test_buffer,
880 GLenum color_buffer_zero_format)
882 int maxBuffers;
883 glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxBuffers);
885 /* Ensure that requested number of color attachments are
886 * supported by the implementation and fragment shader.
888 if (n_attachments <= (int) ARRAY_SIZE(draw_buffers) &&
889 n_attachments <= maxBuffers)
890 num_draw_buffers = n_attachments;
891 else {
892 printf("Number of attachments requested are not supported\n");
893 piglit_report_result(PIGLIT_SKIP);
896 pattern_width = width;
897 pattern_height = height;
898 draw_buffer_zero_format = color_buffer_zero_format;
900 /* Setup frame buffer objects with required configuration */
901 FboConfig ms_config(samples, pattern_width, pattern_height);
902 ms_config.color_internalformat = color_buffer_zero_format;
903 ms_fbo.setup(ms_config);
905 /* Create resolve_fbo with dimensions large enough to accommodate
906 * all the draw buffers
908 FboConfig resolve_config(0, pattern_width,
909 num_draw_buffers * pattern_height);
910 resolve_config.color_internalformat = GL_RGBA;
911 resolve_fbo.setup(resolve_config);
913 /* Create resolve_int_fbo to store downsampled integer draw buffer */
914 if (color_buffer_zero_format == GL_RGBA8I) {
915 resolve_config.color_internalformat = GL_RGBA8I;
916 /* Assuming single integer buffer */
917 resolve_config.height = pattern_height;
918 resolve_int_fbo.setup(resolve_config);
919 is_buffer_zero_integer_format = true;
921 else if (color_buffer_zero_format != GL_RGBA &&
922 color_buffer_zero_format != GL_NONE) {
923 printf("Draw buffer zero format is not"
924 " supported by test functions.\n");
925 piglit_report_result(PIGLIT_FAIL);
928 if (!piglit_check_gl_error(GL_NO_ERROR)) {
929 printf("Error setting up frame buffer objects\n");
930 piglit_report_result(PIGLIT_FAIL);
933 /* Query the number of samples used in ms_fbo. OpenGL implementation
934 * may create FBO with more samples per pixel than what is requested.
936 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);
937 glGetIntegerv(GL_SAMPLES, &num_samples);
939 /* Attach additional color buffers to multisample FBO with default
940 * non-integer format (GL_RGBA.)
942 GLuint *color_rb = (GLuint *)malloc((num_draw_buffers - 1) *
943 sizeof(GLuint));
944 glGenRenderbuffers(num_draw_buffers - 1, color_rb);
946 for (int i = 0; i < num_draw_buffers - 1; i++) {
947 glBindRenderbuffer(GL_RENDERBUFFER, color_rb[i]);
948 glRenderbufferStorageMultisample(GL_RENDERBUFFER,
949 ms_fbo.config.num_samples,
950 GL_RGBA,
951 ms_fbo.config.width,
952 ms_fbo.config.height);
954 glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,
955 GL_COLOR_ATTACHMENT0 + (i + 1),
956 GL_RENDERBUFFER,
957 color_rb[i]);
960 GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);
961 if (status != GL_FRAMEBUFFER_COMPLETE) {
962 printf("Error attaching additional color buffers\n");
963 piglit_report_result(PIGLIT_FAIL);
965 buffer_to_test = test_buffer;
966 free(color_rb);