On 11 July 2012 16:16, Anuj Phogat <span dir="ltr"><<a href="mailto:anuj.phogat@gmail.com" target="_blank">anuj.phogat@gmail.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">



Functions defined in these files are utilized by following test cases:<br>
draw-buffers-alpha-to-one<br>
int-draw-buffers-alpha-to-one<br>
draw-buffers-alpha-to-coverage<br>
int-draw-buffers-alpha-to-coverage<br>
<br>
Signed-off-by: Anuj Phogat <<a href="mailto:anuj.phogat@gmail.com" target="_blank">anuj.phogat@gmail.com</a>><br>
---<br>
 .../draw-buffers-common.cpp                        |  747 ++++++++++++++++++++<br>
 .../draw-buffers-common.h                          |   60 ++<br>
 2 files changed, 807 insertions(+), 0 deletions(-)<br>
 create mode 100644 tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp<br>
 create mode 100644 tests/spec/ext_framebuffer_multisample/draw-buffers-common.h<br>
<br>
diff --git a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp<br>
new file mode 100644<br>
index 0000000..1ad44bd<br>
--- /dev/null<br>
+++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.cpp<br>
@@ -0,0 +1,747 @@<br>
+/*<br>
+ * Copyright © 2012 Intel Corporation<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include "draw-buffers-common.h"<br>
+<br>
+/**<br>
+ * \file draw-buffers-common.cpp<br>
+ *<br>
+ * This file provides utility functions to draw a test pattern to multiple draw<br>
+ * buffers attached to a FBO with GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE}<br>
+ * enabled / disabled.<br></blockquote><div><br>It seems like a lot of the code in this patch is very similar to code that already exists in sample-alpha-to-coverage.cpp and sample-alpha-to-one.cpp.  How difficult would it be to adapt those existing tests to use the common code?  (I think it would be ok to land this patch series first, and do that refactoring later).<br>
<br>This looks like it's going to be a good set of tests.  I have a bunch of small nit-picks below¸ but in general I like it.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+ *<br>
+ * Expected color values are computed for each draw buffer based on the enabled<br>
+ * GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE} flags and coverage value used to draw the<br>
+ * test pattern.<br>
+ *<br>
+ * Reference image for each draw buffer is drawn in to right half of default<br>
+ * framebuffer. It is used to verify the accuracy of test image as well as to<br>
+ * visually compare the difference caused by enabling above flags.<br>
+ *<br>
+ * Test image is drawn with the same test pattern in multisample buffer with<br>
+ * GL_SAMPLE_ALPHA_TO_{COVERAGE, ONE} enabled. All multisample draw buffers<br>
+ * are sequentially resolved by  blitting them to a single sample FBO. resolve_fbo<br>
+ * is then blitted to left half of window system framebuffer with appropriate y<br>
+ * offset. This produces three test images in the left half, each corresponds to<br>
+ * a color attachment.<br>
+ *<br>
+ * Test image is verified by comparing it with the corresponding reference<br>
+ * image in the right half<br>
+ *<br>
+ * For sample coverage and sample alpha to coverage, test image should be<br>
+ * verified by probing the rectangles in left half of window system framebuffer<br>
+ * and comparing with expected color values. OpenGL 3.0 specification intends to<br>
+ * allow (but not require) the implementation to produce a dithering effect when<br>
+ * the coverage value is not a strict multiple of 1 / num_samples. We will skip<br>
+ * computing expected values and probing for such rectangles. They are drawn<br>
+ * just to look for dithering by human inspection.<br>
+ *<br>
+ * Note: Testing for 3 three draw buffers is supported at present. We have to<br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+ * generate the fragment shader at run time to allow drawing to user specified<br>
+ * number of draw buffers. I'll skip it for now as this doesn't seem to make<br>
+ * any difference to test with different number of draw buffers.<br></blockquote><div><br>I found this paragraph difficult to follow.  You might consider rephrasing the first two sentences to something like this:<br><br>



Note: At present, the test always uses three draw buffers.  To test other numbers of draw buffers, we would have to modify the fragment shader in nontrivial ways at run time.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">




+ *<br>
+ * Testing of integer formats for draw buffer zero other than GL_RGBA8I is not<br>
+ * supported by utility functions in this file.<br>
+ *<br>
+ *<br>
+ * Author: Anuj Phogat <<a href="mailto:anuj.phogat@gmail.com" target="_blank">anuj.phogat@gmail.com</a>><br>
+ */<br>
+<br>
+static Fbo ms_fbo, resolve_fbo, resolve_int_fbo;<br>
+static GLbitfield buffer_to_test;<br>
+<br>
+static float *coverage = NULL;<br>
+static float *color = NULL;<br>
+static float *expected = NULL;<br>
+<br>
+static int num_draw_buffers;<br>
+static int num_samples;<br>
+static int num_rects;<br>
+static int prog;<br>
+static int color_loc;<br>
+static int icolor_loc;<br>
+static int alpha_to_coverage_loc;<br>
+static int pattern_width;<br>
+static int pattern_height;<br>
+<br>
+static bool is_buffer_zero_integer_format = false;<br>
+<br>
+static const int num_components = 4; /* for RGBA formats */<br>
+static const int num_color_bits = 8; /* for GL_RGBA & GL_RGBA8I formats */<br>
+<br>
+static const float bg_color[4] = {<br>
+       0.0, 0.6, 0.0, 0.4 };<br>
+<br>
+/* Testing for three draw buffers is supported */<br>
+static const GLenum draw_buffers[] = {<br>
+       GL_COLOR_ATTACHMENT0_EXT,<br>
+       GL_COLOR_ATTACHMENT1_EXT,<br>
+       GL_COLOR_ATTACHMENT2_EXT };<br>
+<br>
+static const char *vert =<br>
+       "#version 130\n"<br>
+       "in vec2 pos;\n"<br>
+       "uniform float depth;\n"<br>
+       "void main()\n"<br>
+       "{\n"<br>
+       "  gl_Position = gl_ModelViewProjectionMatrix * vec4(pos, 0.0, 1.0);\n"<br>
+       "}\n";<br>
+<br>
+/* Fragment shader outputs to three draw buffers. Output different alpha values<br>
+ * to different draw buffers. This is required to verify that alpha values from<br>
+ * draw buffer zero are used to determine the fragment coverage value for all<br>
+ * the draw buffers.<br>
+ */<br>
+static const char *frag_template =<br>
+       "#version 130\n"<br>
+       "#define OUT_TYPE %s\n"<br>
+       "out OUT_TYPE frag_out_0;\n"<br>
+       "out vec4 frag_out_1;\n"<br>
+       "out vec4 frag_out_2;\n"<br>
+       "uniform OUT_TYPE icolor;\n"<br></blockquote><div><br>It's kind of confusing to call this variable "icolor" because it's not always an integer variable.  How about "frag0color" or something?<br>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+       "uniform vec4 color;\n"<br>
+       "uniform bool alphatocoverage;\n"<br>
+       "void main()\n"<br>
+       "{\n"<br>
+       "  frag_out_0 = icolor;\n"<br>
+       "  if(alphatocoverage) {\n"<br>
+       "    frag_out_1 = vec4(color.rgb, color.a / 2);\n"<br>
+       "    frag_out_2 = vec4(color.rgb, color.a / 4);\n"<br>
+       "  }\n"<br>
+       "  else {\n"<br>
+       "    frag_out_1 = frag_out_2 = color;\n"<br>
+       "  }\n"<br>
+       "}\n";<br>
+<br>
+const char *<br>
+get_out_type_glsl(void)<br>
+{<br>
+       if(is_buffer_zero_integer_format)<br>
+               return "ivec4";<br>
+       else<br>
+               return "vec4";<br>
+}<br>
+void<br>
+shader_compile(void)<br>
+{<br>
+       /* Compile program */<br>
+       GLint vs = piglit_compile_shader_text(GL_VERTEX_SHADER, vert);<br>
+<br>
+       const char *out_type_glsl = get_out_type_glsl();;<br>
+        unsigned frag_alloc_len = strlen(frag_template) +<br>
+                                 strlen(out_type_glsl) + 1;<br>
+       char *frag = (char *) malloc(frag_alloc_len);<br>
+       sprintf(frag, frag_template, out_type_glsl);<br>
+<br>
+       GLint fs = piglit_compile_shader_text(GL_FRAGMENT_SHADER, frag);<br></blockquote><div><br>It doesn't really matter since this is a piglit test, but we should probably free(frag) here.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">




+       prog = piglit_link_simple_program(vs, fs);<br>
+<br>
+       if (!piglit_link_check_status(prog)) {<br>
+               piglit_report_result(PIGLIT_FAIL);<br>
+       }<br>
+<br>
+       glBindFragDataLocation(prog, 0, "frag_out_0");<br>
+       glBindFragDataLocation(prog, 1, "frag_out_1");<br>
+       glBindFragDataLocation(prog, 2, "frag_out_2");<br>
+<br>
+       glBindAttribLocation(prog, 0, "pos");<br>
+       glEnableVertexAttribArray(0);<br>
+<br>
+       /* Linking is rquired after glBindFragDataLocation */<br>
+       piglit_LinkProgram(prog);<br>
+<br>
+       /* Set up uniforms */<br>
+       glUseProgram(prog);<br>
+       color_loc = glGetUniformLocation(prog, "color");<br>
+       icolor_loc = glGetUniformLocation(prog, "icolor");<br>
+       alpha_to_coverage_loc = glGetUniformLocation(prog, "alphatocoverage");<br>
+}<br>
+<br>
+void<br>
+allocate_data_arrays(void)<br>
+{<br>
+       /* Draw 2N + 1 rectangles for N samples, each with a unique color<br>
+        * and coverage value<br>
+        */<br>
+       num_rects = 2 * num_samples + 1;<br>
+<br>
+       /* Allocate data arrays based on number of samples used */<br>
+       color = (float *) malloc(num_rects * num_components * sizeof(float));<br>
+       coverage = (float *) malloc(num_rects * sizeof(float));<br>
+       expected = (float *) malloc(num_draw_buffers * num_rects *<br>
+                                   num_components * sizeof(float));<br>
+<br>
+       for(int i = 0; i < num_rects; i++) {<br>
+               unsigned rect_idx = i * num_components;<br>
+               for(int j = 0; j < num_components - 1; j++) {<br>
+                       color[rect_idx + j] =<br>
+                       (sin((float)(rect_idx + j)) + 1) / 2;<br>
+               }<br>
+               /* Alpha value will be directly used as coverage */<br>
+               if (num_samples)<br>
+                       color[rect_idx + 3] = i * (1.0 / (2.0 * num_samples));<br>
+               else<br>
+                       color[rect_idx + 3] = 1.0;<br>
+       }<br>
+} <br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+void<br>
+free_data_arrays(void)<br>
+{<br>
+       if(color != NULL) {<br>
+               free(color);<br>
+               color = NULL;<br>
+       }<br>
+       if(coverage != NULL) {<br>
+               free(coverage);<br>
+               coverage = NULL;<br>
+       }<br>
+       if(expected != NULL) {<br>
+               free(expected);<br>
+               expected = NULL;<br>
+       }<br>
+}<br></blockquote><div><br>FYI, it is safe to pass a NULL pointer to free() (it does nothing if you do), so this could be rewritten as:<br><br>void<br>free_data_arrays(void)<br>{<br>  free(color);<br>  color = NULL;<br>



  free(coverage);<br>  coverage = NULL;<br>  free(expected);<br>  expected = NULL;<br>}<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+void<br>
+float_color_to_int_color(int *dst, float *src)<br>
+{<br>
+       if(!dst || !src) {<br>
+               printf("Null src/dst pointer\n");<br>
+               exit(1);<br>
+       }<br></blockquote><div><br>This check isn't really necessary IMHO.  If src or dst is null, the loop below will segfault, and the programmer will have no less information to debug the problem.  (In fact, if they have core dumps enabled, they will have even more information, since they will have a core dump).<br>


 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+       float offset = 1 - pow(2, (num_color_bits - 1));<br>
+       float scale = -2.0 * offset;<br>
+<br>
+       for (int j = 0; j < num_rects; ++j) {<br>
+               for (int k = 0; k < num_components; ++k) {<br>
+                       dst[j * num_components + k] =<br>
+                       scale * src[j * num_components + k] + offset;<br>
+               }<br>
+       }<br>
+}<br>
+<br>
+void<br>
+draw_pattern(bool sample_alpha_to_coverage,<br>
+            bool sample_alpha_to_one,<br>
+            bool is_reference_image,<br>
+            float *float_color)<br>
+{<br>
+       glUseProgram(prog);<br>
+       glClearColor(bg_color[0], bg_color[1],<br>
+                    bg_color[2], bg_color[3]);<br>
+       glClear(buffer_to_test);<br>
+<br>
+       if (sample_alpha_to_coverage) {<br>
+               if(!is_reference_image)<br>
+                       glEnable (GL_SAMPLE_ALPHA_TO_COVERAGE);<br>
+               glUniform1i(alpha_to_coverage_loc, true);<br>
+       }<br>
+       else<br>
+               glUniform1i(alpha_to_coverage_loc, false);<br>
+<br>
+       if (!is_reference_image && sample_alpha_to_one)<br>
+               glEnable (GL_SAMPLE_ALPHA_TO_ONE);<br></blockquote><div><br>I think this would read more easily if we split the code to set the uniform from the code to set up the GL state, e.g.:<br><br>glUniform1i(alpha_to_coverage_loc, sample_alpha_to_coverage);<br>

if (!is_reference_image) {<br>  if (sample_alpha_to_coverage)<br>    glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);<br>  if (sample_alpha_to_one)<br>    glEnable(GL_SAMPLE_ALPHA_TO_ONE);<br>}<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">


+<br>
+       unsigned indices[6] = {0, 1, 2, 0, 2, 3};<br>
+       int integer_color[num_rects * num_components];<br>
+<br>
+       /* For integer color buffers convert the color data to integer format */<br>
+        if(is_buffer_zero_integer_format) {<br>
+               float_color_to_int_color(integer_color, float_color);<br>
+       }<br>
+<br>
+       for (int i = 0; i < num_rects; ++i) {<br>
+               float vertices[4][2] = {<br>
+               { 0.0f, 0.0f + i * (pattern_height / num_rects) },<br>
+               { 0.0f, (i + 1.0f) * (pattern_height / num_rects) },<br>
+               { pattern_width, (i + 1.0f) * (pattern_height / num_rects) },<br>
+               { pattern_width, 0.0f + i * (pattern_height / num_rects) } };<br>
+<br>
+               glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE,<br>
+                                     sizeof(vertices[0]),<br>
+                                     (void *) vertices);<br>
+<br>
+               glUniform4fv(color_loc, 1, (float_color + i * num_components));<br>
+               if(is_buffer_zero_integer_format) {<br>
+                       glUniform4iv(icolor_loc, 1,<br>
+                                    integer_color + i * num_components);<br>
+               }<br>
+               else {<br>
+                       glUniform4fv(icolor_loc, 1,<br>
+                                    (float_color + i * num_components));<br>
+               }<br>
+               glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT,<br>
+                              (void *) indices);<br>
+       }<br>
+<br>
+       if (!is_reference_image) {<br>
+               if (sample_alpha_to_coverage)<br>
+                       glDisable (GL_SAMPLE_ALPHA_TO_COVERAGE);<br>
+<br>
+               if (sample_alpha_to_one)<br>
+                       glDisable (GL_SAMPLE_ALPHA_TO_ONE);<br>
+       }<br></blockquote><div><br>Personally I would just replace this with<br><br>glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);<br>glDisable(GL_SAMPLE_ALPHA_TO_ONE);<br><br>There's no harm, and it makes it manifestly obvious that those bits will be disabled when the function returns.<br>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+}<br>
+<br>
+void<br>
+compute_expected(bool sample_alpha_to_coverage,<br>
+                bool sample_alpha_to_one,<br>
+                int draw_buffer_count)<br>
+{<br>
+       int i, j;<br>
+       unsigned buffer_idx_offset = draw_buffer_count *<br>
+                                    num_rects *<br>
+                                    num_components;<br>
+<br>
+       /* Compute the coverage value used in the test */<br>
+       if (num_samples &&<br>
+           sample_alpha_to_coverage &&<br>
+           !is_buffer_zero_integer_format) {<br>
+<br>
+               for (i = 0; i < num_rects; i++) {<br>
+                       /* Coverege value for all the draw buffers comes from<br></blockquote><div><br>"coverage"<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+                        * the fragment alpha values of draw buffer zero<br>
+                        */<br>
+                       float frag_alpha = color[i * num_components + 3];<br>
+                       coverage[i] = (frag_alpha < 1.0) ? frag_alpha : 1.0;<br>
+               }<br>
+       }<br>
+       else {<br>
+               for (i = 0; i < num_rects; i++)<br>
+                       coverage[i] = 1.0;<br>
+       }<br>
+<br>
+       /* Coverage value decides the number of samples in multisample buffer<br>
+        * covered by an incoming fragment, which will then receive the<br>
+        * fragment data. When the multisample buffer is resolved it gets<br>
+        * blended with the background color which is written to the remaining<br>
+        * samples.<br>
+        * Page 254 (page 270 of the PDF) of the OpenGL 3.0 spec says:<br>
+        * "The method of combination is not specified, though a simple average<br>
+        * computed independently for each color component is recommended."<br>
+        * This is followed by NVIDIA and AMD in their proprietary drivers.<br>
+        */<br>
+       for (i = 0; i < num_rects; i++) {<br>
+<br>
+               float samples_used = coverage[i] * num_samples;<br>
+               /* Exepected color values are computed only for integer<br></blockquote><div><br>"expected"<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+                * number of samples_used. Non-integer values may result<br>
+                * in dithering effect.<br>
+                */<br>
+               if(samples_used == (int) samples_used) {<br>
+                       int rect_idx_offset = buffer_idx_offset +<br>
+                                             i * num_components;<br>
+                       for (j = 0; j < num_components - 1 ; j++) {<br>
+<br>
+                               expected[rect_idx_offset + j] =<br>
+                               color[i * num_components + j] * coverage[i] +<br>
+                               bg_color[j] * (1 - coverage[i]);<br>
+                       }<br>
+<br>
+                       /* Compute expected alpha values of draw buffers */<br>
+                       float frag_alpha = color[i * num_components + 3];<br>
+                       int alpha_idx = rect_idx_offset + 3;<br>
+<br>
+                       if ((!num_samples &&<br>
+                            !sample_alpha_to_coverage) ||<br>
+                           is_buffer_zero_integer_format) {<br>
+                               /* Taking in account alpha values modified by<br>
+                                * fragment shader.<br>
+                                */<br>
+                               expected[alpha_idx] =<br>
+                                       is_buffer_zero_integer_format ?<br>
+                                       frag_alpha / pow(2, draw_buffer_count) :<br>
+                                       frag_alpha;<br>
+                       }<br>
+                       else if (sample_alpha_to_coverage) {<br>
+                               /* Taking in account alpha values modified by<br>
+                                * fragment shader.<br>
+                                */<br>
+                               frag_alpha /= pow(2, draw_buffer_count);<br>
+                               if(sample_alpha_to_one) {<br>
+                                       expected[alpha_idx] =<br>
+                                       1.0 * coverage[i] +<br>
+                                       bg_color[3] * (1 - coverage[i]);<br>
+                               }<br>
+                               else {<br>
+                                       expected[alpha_idx] =<br>
+                                       frag_alpha * coverage[i] +<br>
+                                       bg_color[3] * (1 - coverage[i]);<br>
+                               }<br>
+                       }<br>
+                       else {<br>
+                               expected[alpha_idx] =<br>
+                                       sample_alpha_to_one ? 1.0 : frag_alpha;<br>
+                       }<br>
+               }<br>
+       }<br>
+}<br>
+<br>
+/* This function probes all the draw buffers blitted to downsampled FBO<br>
+ * (resolve_fbo / resolve_int_fbo) and compare against expected color values.<br>
+ */<br>
+bool<br>
+probe_framebuffer_color(void)<br>
+{<br>
+       bool result = true;<br>
+       int * expected_int_color = NULL;<br>
+       int rect_width = pattern_width;<br>
+       int rect_height = pattern_height / num_rects;<br>
+<br>
+       for (int i = 0; i < num_draw_buffers; i++) {<br>
+               bool is_integer_operation = is_buffer_zero_integer_format && !i;<br>
+<br>
+               if(is_integer_operation) {<br>
+                       glBindFramebuffer(GL_READ_FRAMEBUFFER,<br>
+                                         resolve_int_fbo.handle);<br>
+                       expected_int_color = (int*) malloc(num_rects *<br>
+                                                          num_components *<br>
+                                                          sizeof(int));<br>
+               }<br>
+               else {<br>
+                       glBindFramebuffer(GL_READ_FRAMEBUFFER,<br>
+                                         resolve_fbo.handle);<br>
+               }<br>
+<br>
+               for (int j = 0; j < num_rects; j++) {<br>
+                       float samples_used = coverage[j] * num_samples;<br>
+                       int rect_x = 0;<br>
+                       int rect_y = i * pattern_height +<br>
+                                    j * (pattern_height / num_rects);<br>
+                       int rect_idx_offset = (i * num_rects + j) *<br>
+                                             num_components;<br>
+<br>
+                       /* Only probe rectangles with coverage value which is a<br>
+                        * strict  multiple of 1 / num_samples.<br>
+                        */<br>
+                       if(samples_used == (int)samples_used) {<br>
+                               if(is_integer_operation) {<br>
+                                       float_color_to_int_color(expected_int_color,<br>
+                                                                expected);<br>
+                                       result = piglit_probe_rect_rgba_int(<br>
+                                                rect_x,<br>
+                                                rect_y,<br>
+                                                rect_width,<br>
+                                                rect_height,<br>
+                                                expected_int_color +<br>
+                                                rect_idx_offset)<br>
+                                                && result;<br>
+                               }<br>
+                               else {<br>
+                                       result = piglit_probe_rect_rgba(<br>
+                                                rect_x,<br>
+                                                rect_y,<br>
+                                                rect_width,<br>
+                                                rect_height,<br>
+                                                expected + rect_idx_offset)<br>
+                                                && result;<br>
+                               }<br>
+                       }<br>
+               }<br>
+       }<br>
+       if(expected_int_color)<br>
+               free(expected_int_color);<br>
+       return result;<br>
+}<br>
+<br>
+/**<br>
+ * Alpha values are visualized by blending the image with a grayscale<br>
+ * checkerboard.<br>
+ */<br>
+void<br>
+visualize_image(float *img, bool lhs, int draw_buffer_count)<br></blockquote><div><br>This function looks almost exactly like the visualize_image() function in formats.cpp.  Can we share this code?<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+{<br>
+       float *visualization = (float *) malloc(sizeof(float) * 3 *<br>
+                              pattern_width * pattern_height);<br>
+       for (int y = 0; y < pattern_height; ++y) {<br>
+               for (int x = 0; x < pattern_width; ++x) {<br>
+                       float r = 0, g = 0, b = 0, a = 1;<br>
+                       float *pixel =<br>
+                               &img[(y * pattern_width + x) * num_components];<br>
+                       r = pixel[0];<br>
+                       g = pixel[1];<br>
+                       b = pixel[2];<br>
+                       a = pixel[3];<br>
+<br>
+                       float checker = ((x ^ y) & 0x10) ? 0.75 : 0.25;<br>
+                       r = r * a + checker * (1 - a);<br>
+                       g = g * a + checker * (1 - a);<br>
+                       b = b * a + checker * (1 - a);<br>
+<br>
+                       visualization[(y * pattern_width + x) * 3] = r;<br>
+                       visualization[(y * pattern_width + x) * 3 + 1] = g;<br>
+                       visualization[(y * pattern_width + x) * 3 + 2] = b;<br>
+               }<br>
+       }<br>
+       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);<br>
+       glViewport(0, 0, pattern_width, pattern_height);<br>
+       glUseProgram(0);<br>
+       glWindowPos2f(lhs ? 0 : pattern_width,<br>
+                     draw_buffer_count * pattern_height);<br>
+       glDrawPixels(pattern_width, pattern_height, GL_RGB, GL_FLOAT,<br>
+                    visualization);<br>
+       free(visualization);<br>
+       free(img);<br></blockquote><div><br>It seems weird for this function to free the input image as a side effect.  I'd recommend doing it in the caller.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+}<br>
+<br>
+void<br>
+draw_image_to_window_system_fb(int draw_buffer_count, bool lhs)<br>
+{<br>
+       unsigned rect_x = 0;<br>
+       unsigned rect_y = draw_buffer_count * pattern_height;<br>
+       unsigned array_size = num_components * pattern_width * pattern_height;<br>
+       float *image = (float *) malloc(sizeof(float) * array_size);<br>
+<br>
+       if(is_buffer_zero_integer_format && draw_buffer_count == 0) {<br>
+               glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_int_fbo.handle);<br>
+               int *tmp = (int *) malloc(sizeof(int) * array_size);<br>
+               glReadPixels(rect_x, rect_y,<br>
+                            pattern_width, pattern_height,<br>
+                            GL_RGBA_INTEGER,<br>
+                            GL_INT, tmp);<br>
+               for (unsigned i = 0; i < array_size; ++i) {<br>
+                       image[i] = tmp[i];<br>
+               }<br>
+<br>
+               /* Convert integer color data to float color data */<br>
+               float color_offset = 1.0 - pow(2.0, num_color_bits - 1);<br>
+               float color_scale = -2.0 * color_offset;<br>
+<br>
+               for (unsigned i = 0; i < array_size; ++i) {<br>
+                       image[i] = (image[i] - color_offset) / color_scale;<br>
+               }<br>
+               free(tmp);<br>
+       }<br>
+       else{<br>
+               glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo.handle);<br>
+               glReadPixels(rect_x, rect_y,<br>
+                            pattern_width,<br>
+                            pattern_height,<br>
+                            GL_RGBA,<br>
+                            GL_FLOAT, image);<br>
+       }<br>
+       visualize_image(image, lhs, draw_buffer_count);<br>
+}<br>
+<br>
+void<br>
+draw_test_image(bool sample_alpha_to_coverage, bool sample_alpha_to_one)<br>
+{<br>
+       /* Draw test pattern in multisample ms_fbo with<br>
+        * GL_SAMPLE_ALPHA_TO_COVERAGE enabled<br>
+        */<br>
+       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);<br>
+       glDrawBuffers(num_draw_buffers, draw_buffers);<br>
+       ms_fbo.set_viewport();<br>
+<br>
+       draw_pattern(sample_alpha_to_coverage,<br>
+                    sample_alpha_to_one,<br>
+                    false /* is_reference_image */,<br>
+                    color);<br>
+<br>
+       for(int i = 0; i < num_draw_buffers; i++) {<br>
+<br>
+               /* Blit ms_fbo to singlesample FBO to resolve multisample<br>
+                * buffer.<br>
+                */<br>
+               glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);<br>
+               glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i);<br>
+<br>
+               if ( is_buffer_zero_integer_format && !i)<br>
+                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,<br>
+                                         resolve_int_fbo.handle);<br>
+               else<br>
+                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,<br>
+                                         resolve_fbo.handle);<br>
+<br>
+               /* Blit all the draw buffers to resolve_fbo / resolve_int_fbo<br>
+                * with different y_offset.<br>
+                */<br>
+               unsigned y_offset = i * pattern_height;<br>
+               glBlitFramebuffer(0, 0,<br>
+                                 pattern_width, pattern_height,<br>
+                                 0, y_offset,<br>
+                                 pattern_width, pattern_height + y_offset,<br>
+                                 buffer_to_test, GL_NEAREST);<br>
+<br>
+               draw_image_to_window_system_fb(i /* draw_buffer_count */,<br>
+                                              true /* lhs */);<br>
+<br>
+               /* Expected color values for all the draw buffers are computed<br>
+                * to aid probe_framebuffer_color() in verification.<br>
+                */<br>
+               if(sample_alpha_to_coverage) {<br>
+                       /* Expected color is different for different draw<br>
+                        * buffers<br>
+                        */<br>
+                       compute_expected(sample_alpha_to_coverage,<br>
+                                        sample_alpha_to_one,<br>
+                                        i /* draw_buffer_count */);<br>
+               }<br>
+       }<br>
+}<br>
+<br>
+void<br>
+draw_reference_image(bool sample_alpha_to_coverage, bool sample_alpha_to_one)<br>
+{<br>
+       /* Draw test pattern in multisample ms_fbo with<br>
+        * GL_SAMPLE_ALPHA_TO_COVERAGE disabled.<br>
+        */<br>
+       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);<br>
+       glDrawBuffers(num_draw_buffers, draw_buffers);<br>
+       ms_fbo.set_viewport();<br>
+<br>
+       if(sample_alpha_to_coverage) {<br>
+               draw_pattern(sample_alpha_to_coverage,<br>
+                            sample_alpha_to_one,<br>
+                            true /* is_reference_image */,<br>
+                            color);<br>
+       }<br>
+       else {<br>
+               /* Value of draw_buffer_count doesn't matter in this case */<br>
+               compute_expected(sample_alpha_to_coverage,<br>
+                                sample_alpha_to_one,<br>
+                                0 /* draw_buffer_count */);<br>
+               draw_pattern(sample_alpha_to_coverage,<br>
+                            sample_alpha_to_one,<br>
+                            true /* is_reference_image */,<br>
+                            expected);<br>
+       }<br>
+<br>
+       for(int i = 0; i < num_draw_buffers; i++) {<br>
+<br>
+               /* Blit ms_fbo to resolve_fbo to resolve multisample buffer */<br>
+               glBindFramebuffer(GL_READ_FRAMEBUFFER, ms_fbo.handle);<br>
+               glReadBuffer(GL_COLOR_ATTACHMENT0_EXT + i);<br>
+               if (is_buffer_zero_integer_format && !i) {<br>
+                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,<br>
+                                         resolve_int_fbo.handle);<br>
+               }<br>
+               else {<br>
+                       glBindFramebuffer(GL_DRAW_FRAMEBUFFER,<br>
+                                         resolve_fbo.handle);<br>
+               }<br>
+<br>
+               /* Blit all the draw buffers to resolve_fbo with different<br>
+                * y_offset.<br>
+                */<br>
+               unsigned y_offset = i * pattern_height;<br>
+               glBlitFramebuffer(0, 0,<br>
+                                 pattern_width, pattern_height,<br>
+                                 0, y_offset,<br>
+                                 pattern_width, pattern_height + y_offset,<br>
+                                 buffer_to_test, GL_NEAREST);<br>
+<br>
+               draw_image_to_window_system_fb(i /* buffer_count */,<br>
+                                              false  /* lhs */ );<br>
+       }<br>
+}<br>
+<br>
+void<br>
+ms_fbo_and_draw_buffers_setup(int samples,<br>
+                             int width,<br>
+                             int height,<br>
+                             int n_attachments,<br>
+                             GLenum buffer_zero_format)<br>
+{<br>
+       int maxBuffers;<br>
+       glGetIntegerv(GL_MAX_COLOR_ATTACHMENTS, &maxBuffers);<br>
+<br>
+       /* Ensure that requested number of color attachments are<br>
+        * supported by the implementation and fragment shader.<br>
+        */<br>
+       if (n_attachments <= (int) ARRAY_SIZE(draw_buffers) &&<br>
+           n_attachments <= maxBuffers)<br>
+               num_draw_buffers = n_attachments;<br>
+       else<br>
+               printf("Number of attachments requested are not supported\n");<br></blockquote><div><br>In the else block, we should probably add "piglit_report_result(PIGLIT_SKIP);" so that the test just skips on implementations that don't support enough attachment points.<br>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
+       pattern_width = width;<br>
+       pattern_height = height;<br>
+<br>
+       /* Setup frame buffer objects with required configuration */<br>
+       FboConfig ms_config(samples, pattern_width, pattern_height);<br>
+       ms_config.color_internalformat = buffer_zero_format;<br>
+       ms_fbo.setup(ms_config);<br>
+<br>
+       /* Create resolve_fbo with dimensions large enough to accomodate<br>
+        * all the draw buffers<br>
+        */<br>
+       FboConfig resolve_config(0, pattern_width,<br>
+                                num_draw_buffers * pattern_height);<br>
+       resolve_config.color_internalformat = GL_RGBA;<br>
+       resolve_fbo.setup(resolve_config);<br>
+<br>
+       /* Create resolve_int_fbo to store downsampled integer draw buffer */<br>
+       if (buffer_zero_format == GL_RGBA8I) {<br>
+               resolve_config.color_internalformat = GL_RGBA8I;<br>
+               /* Assuming single integer buffer */<br>
+               resolve_config.height = pattern_height;<br>
+               resolve_int_fbo.setup(resolve_config);<br>
+               is_buffer_zero_integer_format = true;<br>
+       }<br>
+       else if (buffer_zero_format != GL_RGBA){<br>
+               printf("Draw buffer zero format is not"<br>
+                      " supported by test functions.\n");<br>
+               piglit_report_result(PIGLIT_SKIP);<br></blockquote><div><br>This should only happen if there is a bug in the piglit test, right?  (because the caller passed an unexpected value to ms_fbo_and_draw_buffers_setup())  In that case, this should be PIGLIT_FAIL so that we notice the problem and fix it.  PIGLIT_SKIP should just be for situations where the test is inapplicable because the underlying GL implementation is missing a required extension (or something similar).<br>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+       }<br>
+<br>
+        if (!piglit_check_gl_error(GL_NO_ERROR)) {<br>
+               printf("Error setting up frame buffer objects\n");<br>
+               piglit_report_result(PIGLIT_FAIL);<br>
+        }<br>
+<br>
+       /* Query the number of samples used in ms_fbo. OpenGL implementation<br>
+        * may create FBO with more samples per pixel than what is requested.<br>
+        */<br>
+       glBindFramebuffer(GL_DRAW_FRAMEBUFFER, ms_fbo.handle);<br>
+       glGetIntegerv(GL_SAMPLES, &num_samples);<br>
+<br>
+       /* Attach additional color buffers to multisample FBO with default<br>
+        * non-integer format (GL_RGBA.)<br>
+        */<br>
+       GLuint color_rb[num_draw_buffers - 1];<br>
+       glGenRenderbuffers(num_draw_buffers - 1, color_rb);<br>
+<br>
+       for(int i = 0; i < num_draw_buffers - 1; i++) {<br>
+               glBindRenderbuffer(GL_RENDERBUFFER, color_rb[i]);<br>
+               glRenderbufferStorageMultisample(GL_RENDERBUFFER,<br>
+                                       ms_fbo.config.num_samples,<br>
+                                       GL_RGBA,<br>
+                                       ms_fbo.config.width,<br>
+                                       ms_fbo.config.height);<br>
+<br>
+               glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER,<br>
+                                         GL_COLOR_ATTACHMENT0 + (i + 1),<br>
+                                         GL_RENDERBUFFER,<br>
+                                         color_rb[i]);<br>
+       }<br>
+<br>
+       GLenum status = glCheckFramebufferStatus(GL_DRAW_FRAMEBUFFER);<br>
+        if (status != GL_FRAMEBUFFER_COMPLETE) {<br>
+               printf("Error attaching additional color buffers\n");<br>
+               piglit_report_result(PIGLIT_FAIL);<br>
+       }<br>
+       buffer_to_test = GL_COLOR_BUFFER_BIT;<br>
+}<br>
diff --git a/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h<br>
new file mode 100644<br>
index 0000000..7e6972c<br>
--- /dev/null<br>
+++ b/tests/spec/ext_framebuffer_multisample/draw-buffers-common.h<br>
@@ -0,0 +1,60 @@<br>
+/* Copyright © 2012 Intel Corporation<br>
+ *<br>
+ * Permission is hereby granted, free of charge, to any person obtaining a<br>
+ * copy of this software and associated documentation files (the "Software"),<br>
+ * to deal in the Software without restriction, including without limitation<br>
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,<br>
+ * and/or sell copies of the Software, and to permit persons to whom the<br>
+ * Software is furnished to do so, subject to the following conditions:<br>
+ *<br>
+ * The above copyright notice and this permission notice (including the next<br>
+ * paragraph) shall be included in all copies or substantial portions of the<br>
+ * Software.<br>
+ *<br>
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL<br>
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING<br>
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS<br>
+ * IN THE SOFTWARE.<br>
+ */<br>
+<br>
+#include "common.h"<br>
+<br>
+/**<br>
+ * \file draw-buffers-common.h<br>
+ * This file declares common functions which are used by multiple draw buffer<br>
+ * test cases.<br>
+ */<br>
+<br>
+/* Allocates all the relevant data arrays required in the test */<br>
+void allocate_data_arrays(void);<br>
+<br>
+/* Draws a test pattern without sample_alpha_to_coverage and<br>
+ * sample_alpha_to_one<br>
+ */<br>
+void draw_reference_image(bool sample_alpha_to_coverage,<br>
+                         bool sample_alpha_to_one);<br>
+<br>
+/* Draws the test pattern with either sample_alpha_to_coverage or<br>
+ * sample_alpha_to_one enabled<br>
+ */<br>
+void draw_test_image(bool sample_alpha_to_coverage,<br>
+                    bool sample_alpha_to_one);<br>
+<br>
+/* Frees the previously allocated data arrays */<br>
+void free_data_arrays(void);<br>
+<br>
+/* Initilaizes multisample framebuffer object with multiple draw buffers */<br>
+void ms_fbo_and_draw_buffers_setup(int samples,<br>
+                                  int width, int height,<br>
+                                  int n_attachments,<br>
+                                  GLenum buffer_zero_format);<br>
+<br>
+/* Probe downsampled FBO (resolve_fbo / resolve_int_fbo) to compare against<br>
+ * expected color for each draw buffer<br>
+ */<br>
+bool probe_framebuffer_color(void);<br>
+<br>
+void shader_compile(void);<br>
<span><font color="#888888">--<br>
1.7.7.6<br>
<br>
_______________________________________________<br>
Piglit mailing list<br>
<a href="mailto:Piglit@lists.freedesktop.org" target="_blank">Piglit@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/piglit" target="_blank">http://lists.freedesktop.org/mailman/listinfo/piglit</a><br>
</font></span></blockquote></div><br>