Create the largest possible 2D GL_RGBA_32F multisampled texture, load it
with known values the read it back and see if the values match up.

The --array option runs the test with a 2D texture array instead of an
MSAA texture.  There are other options to specify texture size, number of
samples, fp16 and a texel value scale.

Fails with NVIDIA's driver.  See code comments.

Note: The entry in all.py limits the texture size to 512x512 so it runs
in a reasonable amount of time.  Ideally, the texture size should be set
in quick.py instead but I've been unable to make that work.

v2:
* Fix a few code issues raised by Fabian Bieler, fix all.py, quick.py code.
* Update comments about NVIDIA driver, per Roland.
---
 tests/all.py                                       |   8 +
 tests/quick.py                                     |  17 +
 .../spec/arb_texture_multisample/CMakeLists.gl.txt |   1 +
 .../arb_texture_multisample/large-float-texture.c  | 728 +++++++++++++++++++++
 4 files changed, 754 insertions(+)
 create mode 100644 tests/spec/arb_texture_multisample/large-float-texture.c

diff --git a/tests/all.py b/tests/all.py
index 5d90e8f..d55cca9 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -1651,6 +1651,14 @@ with profile.test_list.group_manager(
 # Group ARB_texture_multisample
 with profile.test_list.group_manager(
         PiglitGLTest, grouptools.join('spec', 'ARB_texture_multisample')) as g:
+    g(['arb_texture_multisample-large-float-texture'], 'large-float-texture',
+      run_concurrent=False)
+    g(['arb_texture_multisample-large-float-texture', '--array'],
+      'large-float-texture-array', run_concurrent=False)
+    g(['arb_texture_multisample-large-float-texture', '--fp16'],
+      'large-float-texture-fp16', run_concurrent=False)
+    g(['arb_texture_multisample-large-float-texture', '--array', '--fp16'],
+      'large-float-texture-array-fp16', run_concurrent=False)
     g(['arb_texture_multisample-minmax'])
     g(['texelFetch', 'fs', 'sampler2DMS', '4', '1x71-501x71'])
     g(['texelFetch', 'fs', 'sampler2DMS', '4', '1x130-501x130'])
diff --git a/tests/quick.py b/tests/quick.py
index 1a7d674..53774e4 100644
--- a/tests/quick.py
+++ b/tests/quick.py
@@ -68,6 +68,23 @@ with profile.test_list.group_manager(
     with profile.test_list.allow_reassignment:
         g(['ext_texture_env_combine-combine', '--quick'], 
'texture-env-combine')
 
+# Limit texture size to 512x512 for some texture_multisample tests.
+# The default (max supported size) can be pretty slow.
+with profile.test_list.group_manager(
+        PiglitGLTest,
+        grouptools.join('spec', 'ARB_texture_multisample')) as g:
+    with profile.test_list.allow_reassignment:
+        size_arg = ['--texsize', '512']
+        g(['arb_texture_multisample-large-float-texture'] + size_arg,
+          'large-float-texture', run_concurrent=False)
+        g(['arb_texture_multisample-large-float-texture', '--array'] +
+          size_arg, 'large-float-texture-array', run_concurrent=False)
+        g(['arb_texture_multisample-large-float-texture', '--fp16'] +
+          size_arg, 'large-float-texture-fp16', run_concurrent=False)
+        g(['arb_texture_multisample-large-float-texture', '--array',
+           '--fp16'] + size_arg,
+          'large-float-texture-array-fp16', run_concurrent=False)
+
 # These take too long
 profile.filters.append(lambda n, _: '-explosion' not in n)
 profile.filters.append(FilterVsIn())
diff --git a/tests/spec/arb_texture_multisample/CMakeLists.gl.txt 
b/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
index a347143..31965c4 100644
--- a/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
+++ b/tests/spec/arb_texture_multisample/CMakeLists.gl.txt
@@ -9,6 +9,7 @@ link_libraries (
        ${OPENGL_gl_LIBRARY}
 )
 
+piglit_add_executable (arb_texture_multisample-large-float-texture 
large-float-texture.c)
 piglit_add_executable (arb_texture_multisample-minmax minmax.c)
 piglit_add_executable (arb_texture_multisample-errors errors.c)
 piglit_add_executable (arb_texture_multisample-fb-completeness 
fb-completeness.c)
diff --git a/tests/spec/arb_texture_multisample/large-float-texture.c 
b/tests/spec/arb_texture_multisample/large-float-texture.c
new file mode 100644
index 0000000..3a77d43
--- /dev/null
+++ b/tests/spec/arb_texture_multisample/large-float-texture.c
@@ -0,0 +1,728 @@
+/*
+ * Copyright (c) 2017 VMware, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file large-float-texture.c
+ *
+ * Test large MSAA float textures.  In particular, create/load a multisample
+ * texture then read it back and compare returned values.
+ * Also support array textures instead of MSAA as a sanity check / debug
+ * option.
+ *
+ * Some drivers/GPUs may fail this test.  NVIDIA, for example, appears to
+ * only store the MSAA coverage info, not the sample colors, for samples
+ * beyond the 8th sample.  We may tune the way this test operates over time
+ * to be more useful.  Maybe we should test all MSAA samples/pixels (2x,
+ * 4x, 8x, etc).
+ *
+ * See code for command line arguments.
+ */
+
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+       config.supports_gl_compat_version = 30;
+       config.window_visual = PIGLIT_GL_VISUAL_RGB | PIGLIT_GL_VISUAL_DOUBLE;
+       config.khr_no_error_support = PIGLIT_NO_ERRORS;
+PIGLIT_GL_TEST_CONFIG_END
+
+
+static bool verbose = false;
+
+
+/**
+ * Try to create a GL_RGBA32F/16F texture of the given size, samples.
+ * Return 0 if failure.
+ */
+static GLuint
+create_texture(GLenum target, GLenum intFormat,
+              GLsizei width, GLsizei height, GLuint numSamples)
+{
+       GLuint tex;
+
+       assert(intFormat == GL_RGBA32F || intFormat == GL_RGBA16F);
+
+       if (verbose) {
+               printf("Trying %d x %d  %d samples/layers\n",
+                      width, height, numSamples);
+       }
+
+       glGenTextures(1, &tex);
+       glBindTexture(target, tex);
+       if (target == GL_TEXTURE_2D_MULTISAMPLE) {
+               glTexImage2DMultisample(target,
+                                       numSamples, intFormat, width, height,
+                                       GL_FALSE); /* fixedsamplelocations */
+       }
+       else {
+               /* instead of samples per pixel, use 'samples' layers */
+               assert(target == GL_TEXTURE_2D_ARRAY);
+               glTexStorage3D(target, 1, intFormat, width, height,
+                              numSamples);
+       }
+
+       if (glGetError() != GL_NO_ERROR) {
+               /* some error */
+               glDeleteTextures(1, &tex);
+               tex = 0;
+       }
+
+       return tex;
+}
+
+
+/**
+ * Find the max working texture size.
+ */
+static GLuint
+create_texture_max_size(GLenum target, GLenum intFormat,
+                       GLsizei *width, GLsizei *height,
+                       GLuint numSamples)
+{
+       GLint w, h;
+       GLuint tex = 0;
+
+       w = *width;
+       h = *height;
+       while (w >= 1 && h >= 1) {
+               tex = create_texture(target, intFormat, w, h, numSamples);
+               if (tex) {
+                       /* done! */
+                       *width = w;
+                       *height = h;
+                       break;
+               }
+               /* try smaller size */
+               if (h >= w) {
+                       h /= 2;
+               }
+               else {
+                       w /= 2;
+               }
+       }
+
+       return tex;
+}
+
+
+/**
+ * Create an FBO which wraps the given texture.
+ */
+static GLuint
+create_fbo(GLuint tex, GLenum texTarget)
+{
+       GLuint fbo;
+
+       assert(texTarget == GL_TEXTURE_2D_MULTISAMPLE ||
+              texTarget == GL_TEXTURE_2D_ARRAY ||
+              texTarget == GL_TEXTURE_2D);
+
+       glGenFramebuffers(1, &fbo);
+       glBindFramebuffer(GL_FRAMEBUFFER, fbo);
+       if (texTarget == GL_TEXTURE_2D_MULTISAMPLE ||
+           texTarget == GL_TEXTURE_2D) {
+               glFramebufferTexture2D(GL_FRAMEBUFFER,
+                                      GL_COLOR_ATTACHMENT0,
+                                      texTarget, tex, 0);  /* 0=level */
+       }
+       else {
+               assert(texTarget == GL_TEXTURE_2D_ARRAY);
+               glFramebufferTextureLayer(GL_FRAMEBUFFER,
+                                         GL_COLOR_ATTACHMENT0,
+                                         tex, 0, 0);
+       }
+
+       GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+       if (status != GL_FRAMEBUFFER_COMPLETE) {
+               if (verbose) {
+                       printf("Failed to create FBO! (status = %s)\n",
+                              piglit_get_gl_enum_name(status));
+               }
+               glDeleteFramebuffers(1, &fbo);
+               fbo = 0;
+       }
+
+       return fbo;
+}
+
+
+/**
+ * Load the GL_RGBA32F/16F MSAA (or array) texture with known values.
+ * The color components are basically:
+ *  x = texcoord in [0, 1]  (this can get fuzzy for large texture widths)
+ *  y = fragcoord.y MOD 16 in [0, 15]
+ *  z = -curSample in [-(numSamples-1), 0]
+ *  w = curSample in [0, numSamples-1]
+ */
+static void
+load_texture_image(GLenum target, GLuint fbo, GLuint tex,
+                  GLsizei width, GLsizei height, GLuint numSamples,
+                  GLfloat valueScale)
+{
+       static const char *vs_text =
+               "#version 130\n"
+               "out vec4 texcoord;\n"
+               "void main() {\n"
+               "  texcoord = gl_MultiTexCoord0;\n"
+               "  gl_Position = gl_Vertex;\n"
+               "}\n";
+       static const char *fs_text =
+               "#version 130\n"
+               "out vec4 color;\n"
+               "in vec4 texcoord;\n"
+               "uniform int curSample;\n"
+               "uniform float valueScale;\n"
+               "void main() {\n"
+               "   float x = texcoord.x; \n"
+               "   float y = float(int(gl_FragCoord.y) % 16) / 16.0; \n"
+               "   float z = -curSample; \n"
+               "   float w = curSample; \n"
+               "   color = valueScale * vec4(x, y, z, w); \n"
+               "}\n";
+
+       GLuint prog;
+
+       prog = piglit_build_simple_program(vs_text, fs_text);
+
+       assert(prog);
+       assert(numSamples <= 32);
+
+       glUseProgram(prog);
+
+       GLint curSampleUniform = glGetUniformLocation(prog, "curSample");
+       assert(curSampleUniform >= 0);
+
+       GLint valueScaleUniform = glGetUniformLocation(prog, "valueScale");
+       glUniform1f(valueScaleUniform, valueScale);
+
+       if (target == GL_TEXTURE_2D_MULTISAMPLE) {
+               glEnable(GL_SAMPLE_MASK);
+               glEnable(GL_MULTISAMPLE);
+       }
+
+       GLint samp;
+       for (samp = 0; samp < numSamples; samp++) {
+               if (verbose) {
+                       printf("Render sample/layer %d\n", samp);
+               }
+
+               glUniform1i(curSampleUniform, samp);
+
+               /* choose sample or layer to write to */
+               if (target == GL_TEXTURE_2D_MULTISAMPLE) {
+                       glSampleMaski(0, 1u << samp);
+               }
+               else {
+                       assert(target == GL_TEXTURE_2D_ARRAY);
+                       glFramebufferTextureLayer(GL_FRAMEBUFFER,
+                                                 GL_COLOR_ATTACHMENT0,
+                                                 tex, 0, samp);
+               }
+
+               /* Full framebuffer rect */
+               piglit_draw_rect_tex(-1, -1, 2, 2,
+                                    0, 0, 1, 1);
+       }
+
+       if (target == GL_TEXTURE_2D_MULTISAMPLE) {
+               glDisable(GL_SAMPLE_MASK);
+               glDisable(GL_MULTISAMPLE);
+       }
+
+       glDeleteProgram(prog);
+}
+
+
+/**
+ * Create simple 2D, GL_RGBA32F texture of given size.
+ */
+static GLuint
+create_float4_tex(GLsizei width, GLsizei height)
+{
+       GLuint tex;
+
+       glGenTextures(1, &tex);
+       glBindTexture(GL_TEXTURE_2D, tex);
+       glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA32F, width, height);
+
+       if (glGetError() != GL_NO_ERROR) {
+               glDeleteTextures(1, &tex);
+               tex = 0;
+       }
+       return tex;
+}
+
+
+/**
+ * Create the shader program needed for extracting texels from an
+ * MSAA (or array) texture.
+ */
+static GLuint
+create_readback_program(GLenum target)
+{
+       static const char *fs_text_msaa =
+               "#version 130\n"
+               "#extension GL_ARB_texture_multisample : enable\n"
+               "out vec4 color;\n"
+               "uniform sampler2DMS tex;\n"
+               "uniform int sample;\n"
+               "void main() {\n"
+               "  ivec2 coord = ivec2(gl_FragCoord.xy);\n"
+               "  color = texelFetch(tex, coord, sample);\n"
+               "}\n";
+
+       static const char *fs_text_array =
+               "#version 130\n"
+               "out vec4 color;\n"
+               "uniform sampler2DArray tex;\n"
+               "uniform int sample;\n"
+               "void main() {\n"
+               "  ivec2 coord = ivec2(gl_FragCoord.xy);\n"
+               "  color = texelFetch(tex, ivec3(coord, sample), 0);\n"
+               "}\n";
+
+       const char *fs_text = target == GL_TEXTURE_2D_MULTISAMPLE ?
+               fs_text_msaa : fs_text_array;
+
+       GLuint prog = piglit_build_simple_program(NULL, fs_text);
+
+       assert(prog);
+
+       return prog;
+}
+
+/**
+ * Extract a slice or per-sample image from the src_tex.
+ */
+static void
+extract_texture_image(GLuint readbackProg,
+                     GLuint src_tex, GLsizei width, GLsizei height,
+                     GLuint sample)
+{
+       glUseProgram(readbackProg);
+
+       GLint texUniform = glGetUniformLocation(readbackProg, "tex");
+       GLint sampleUniform = glGetUniformLocation(readbackProg, "sample");
+
+       /* Create texture to put results into, and wrap it in an FBO.
+        * The shader will extract the sample from the MSAA texture (or
+        * array layer) and write the results into a destination texture/FBO.
+        */
+       GLuint dst_tex = create_float4_tex(width, height);
+       GLuint dst_fbo = create_fbo(dst_tex, GL_TEXTURE_2D);
+
+       glUniform1i(texUniform, 0);  // unit 0
+       glUniform1i(sampleUniform, sample);
+
+       glBindFramebuffer(GL_FRAMEBUFFER, dst_fbo);
+
+       piglit_draw_rect_tex(-1, -1, 2, 2,
+                            0, 0, 1, 1);
+
+       glBindTexture(GL_TEXTURE_2D, dst_tex);
+
+       /* Now, the extracted image is available both as dst_tex
+        * and as the current FBO.
+        */
+}
+
+
+/**
+ * Test if two float[4] values are nearly equal.
+ */
+static bool
+nearly_equal(const GLfloat x[4], const GLfloat y[4])
+{
+       /* XXX this tolerance was chosen emperically */
+       const float maxRelDiff = 0.0005;
+       int i;
+       for (i = 0; i < 4; i++) {
+               float diff = x[i] - y[i];
+               float ax = fabsf(x[i]), ay = fabsf(y[i]);
+               if (diff > MAX2(ax, ay) * maxRelDiff) {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+
+/**
+ * To record +/- max difference between expected and rendered results.
+ */
+struct error_info
+{
+       float min_error[4], max_error[4];
+       float avg_error[4];
+       unsigned num_fail;
+};
+
+
+static void
+init_error_info(struct error_info *err)
+{
+       int i;
+       for (i = 0; i < 4; i++) {
+               err->min_error[i] = 1e20;
+               err->max_error[i] = -1e20;
+               err->avg_error[i] = 0.0;
+       }
+       err->num_fail = 0;
+}
+
+
+static bool
+nonzero(const float a[4])
+{
+       return a[0] != 0.0 ||a[1] != 0.0 ||a[2] != 0.0 ||a[3] != 0.0;
+}
+
+
+static void
+finish_and_print_error_info(struct error_info *err,
+                           GLsizei width, GLsizei height)
+{
+       int i;
+       for (i = 0; i < 4; i++) {
+               err->avg_error[i] /= width * height;
+       }
+       if (verbose ||
+           nonzero(err->min_error) ||
+           nonzero(err->max_error) ||
+           nonzero(err->avg_error)) {
+               printf("Min error: %g %g %g %g\n",
+                      err->min_error[0], err->min_error[1],
+                      err->min_error[2], err->min_error[3]);
+               printf("Max error: %g %g %g %g\n",
+                      err->max_error[0], err->max_error[1],
+                      err->max_error[2], err->max_error[3]);
+               printf("Avg error: %g %g %g %g\n",
+                      err->avg_error[0], err->avg_error[1],
+                      err->avg_error[2], err->avg_error[3]);
+               printf("num_fail: %u\n", err->num_fail);
+       }
+}
+
+
+static void
+update_error_info(struct error_info *err,
+                 const GLfloat a[4], const GLfloat b[4])
+{
+       bool fail = false;
+       int i;
+
+       for (i = 0; i < 4; i++) {
+               float delta = a[i] - b[i];
+               err->min_error[i] = MIN2(err->min_error[i], delta);
+               err->max_error[i] = MAX2(err->max_error[i], delta);
+
+               err->avg_error[i] += fabsf(delta);
+
+               if (delta != 0.0f) {
+                       fail = true;
+               }
+       }
+
+       err->num_fail += (unsigned) fail;
+}
+
+
+static unsigned
+texel_size(GLenum intFormat)
+{
+       switch (intFormat) {
+       case GL_RGBA16F:
+               return 4 * sizeof(GLhalf);
+       case GL_RGBA32F:
+               return 4 * sizeof(GLfloat);
+       default:
+               assert(!"Unexpected texture format");
+       }
+}
+
+
+/**
+ * Read back all texture samples, compare to reference.
+ */
+static bool
+validate_texture_image(GLenum target,
+                      GLenum intFormat,
+                      GLuint readbackProg,
+                      GLuint src_tex,
+                      GLsizei width, GLsizei height, GLuint numSamples,
+                      GLfloat valueScale)
+{
+       /*
+        * Note: this is a little more complicated than just mallocing
+        * a buffer of size width * height * numSamples * texelSize
+        * because we could easily exceed 4GB.  So, we read back the image
+        * in stripes no larger than 512MB.
+        */
+       const size_t buffer_size = 512 * 1024 * 1024;  // 512 MB
+       GLfloat *buffer = malloc(buffer_size);
+       assert(buffer);
+
+       const int bytesPerRow = width * numSamples * texel_size(intFormat);
+       const int stripeHeight = MIN2(buffer_size / bytesPerRow, height);
+
+       bool pass = true;
+       float fwidth = (float) width;
+       GLuint samp;
+
+       glBindTexture(target, src_tex);
+
+       for (samp = 0; samp < numSamples; samp++) {
+               struct error_info err;
+
+               init_error_info(&err);
+
+               if (verbose) {
+                       printf("Checking sample/layer %d\n", samp);
+               }
+
+               extract_texture_image(readbackProg, src_tex,
+                                     width, height, samp);
+
+               GLint i, j, numFail = 0;
+
+               for (j = 0; j < height; j++) {
+
+                       if (j % stripeHeight == 0) {
+                               /* read a stripe */
+                               if (height == stripeHeight) {
+                                       /* get whole texture with GetTexImage */
+                                       glGetTexImage(GL_TEXTURE_2D, 0,
+                                                     GL_RGBA, GL_FLOAT,
+                                                     buffer);
+                               }
+                               else {
+                                       /* use glReadPixels to get a stripe */
+                                       glReadPixels(0, j, width, stripeHeight,
+                                                    GL_RGBA, GL_FLOAT, buffer);
+                               }
+                       }
+
+                       for (i = 0; i < width; i++) {
+                               int row = j % stripeHeight;
+                               const GLfloat *texel =
+                                       buffer + (width * row + i) * 4;
+                               GLfloat expected[4];
+
+                               /* [0] is texcoord at center of fragment */
+                               expected[0] = i / fwidth + (0.5f / fwidth);
+                               /* [1] is fragcoord.y MOD 16 / 16.0 */
+                               expected[1] = (j % 16) / 16.0;
+                               expected[2] = -1.0 * samp;
+                               expected[3] = samp;
+
+                               expected[0] *= valueScale;
+                               expected[1] *= valueScale;
+                               expected[2] *= valueScale;
+                               expected[3] *= valueScale;
+
+                               update_error_info(&err, texel, expected);
+
+                               if (!nearly_equal(texel, expected)) {
+                                       printf("Fail at %d, %d:\n", i, j);
+                                       printf("  Expected %g, %g, %g, %g\n",
+                                              expected[0], expected[1],
+                                              expected[2], expected[3]);
+                                       printf("  Found %g, %g, %g, %g\n",
+                                              texel[0], texel[1],
+                                              texel[2], texel[3]);
+                                       pass = false;
+                                       numFail++;
+                                       if (numFail >= 5) {
+                                               goto end;
+                                       }
+                               }
+                       }
+               }
+               finish_and_print_error_info(&err, width, height);
+       }
+
+end:
+       free(buffer);
+
+       return pass;
+}
+
+
+void
+piglit_init(int argc, char **argv)
+{
+       GLenum target = GL_TEXTURE_2D_MULTISAMPLE;
+       GLenum intFormat = GL_RGBA32F;
+       GLint samples = -1;  /* or array slices */
+       GLint maxSize = -1;
+       GLsizei width = -1, height = -1;
+       GLfloat valueScale = 1.0;
+       int i;
+
+       for (i = 1; i < argc; i++) {
+               if (strcmp(argv[i], "--array") == 0) {
+                       target = GL_TEXTURE_2D_ARRAY;
+               }
+               else if (strcmp(argv[i], "--samples") == 0) {
+                       i++;
+                       samples = atoi(argv[i]);
+                       assert(samples > 0);
+               }
+               else if (strcmp(argv[i], "--texsize") == 0) {
+                       i++;
+                       maxSize = atoi(argv[i]);
+                       assert(maxSize > 0);
+               }
+               else if (strcmp(argv[i], "--width") == 0) {
+                       i++;
+                       width = atoi(argv[i]);
+                       assert(width > 0);
+               }
+               else if (strcmp(argv[i], "--height") == 0) {
+                       i++;
+                       height = atoi(argv[i]);
+                       assert(height > 0);
+               }
+               else if (strcmp(argv[i], "--scale") == 0) {
+                       i++;
+                       valueScale = atof(argv[i]);
+                       assert(valueScale > 0.0);
+               }
+               else if (strcmp(argv[i], "--fp16") == 0) {
+                       intFormat = GL_RGBA16F;
+               }
+               else if (strcmp(argv[i], "--verbose") == 0) {
+                       verbose = true;
+               }
+               else {
+                       printf("Unknown option %s\n", argv[i]);
+                       piglit_report_result(PIGLIT_FAIL);
+               }
+       }
+
+       piglit_require_extension("GL_ARB_texture_float");
+       piglit_require_extension("GL_ARB_texture_multisample");
+       piglit_require_GLSL_version(130);
+
+       if (maxSize == -1) {
+               glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxSize);
+       }
+
+       if (samples == -1) {
+               if (target == GL_TEXTURE_2D_MULTISAMPLE) {
+                       glGetIntegerv(GL_MAX_COLOR_TEXTURE_SAMPLES, &samples);
+               }
+               else {
+                       samples = 16;  /* 16 texture array layers */
+               }
+       }
+
+       GLuint tex, fbo = 0;
+
+       if (width == -1 || height == -1) {
+               width = height = maxSize;
+       }
+
+       while (width > 1 && height > 1) {
+               tex = create_texture_max_size(target, intFormat,
+                                             &width, &height, samples);
+
+               if (!tex) {
+                       printf("Failed to create MSAA texture\n");
+                       piglit_report_result(PIGLIT_FAIL);
+               }
+
+               fbo = create_fbo(tex, target);
+               if (!fbo) {
+                       /* texture creation worked, but FBO failed.
+                        * Try smaller texture.
+                        */
+                       glDeleteTextures(1, &tex);
+                       if (height >= width) {
+                               height /= 2;
+                       }
+                       else {
+                               width /= 2;
+                       }
+               }
+               else {
+                       break;
+               }
+       }
+
+       if (!fbo) {
+               printf("Failed to create FBO\n");
+               piglit_report_result(PIGLIT_SKIP);
+       }
+
+       GLint64 mbytes = (GLint64) width * height * samples
+               * texel_size(intFormat) / (1024 * 1024);
+
+       const char *formatName = piglit_get_gl_enum_name(intFormat);
+       if (target == GL_TEXTURE_2D_ARRAY) {
+               printf("Created %d x %d %d-layer %s texture/FBO"
+                      " (%lld MB)\n",
+                      width, height, samples, formatName,
+                      (long long int) mbytes);
+       }
+       else {
+               printf("Created %d x %d %d-sample MSAA %s texture/FBO"
+                      " (%lld MB)\n",
+                      width, height, samples, formatName,
+                      (long long int) mbytes);
+       }
+
+       GLuint readbackProg = create_readback_program(target);
+
+       glViewport(0, 0, width, height);
+       glClampColor(GL_CLAMP_READ_COLOR, GL_FALSE);
+       glClampColor(GL_CLAMP_FRAGMENT_COLOR, GL_FALSE);
+
+       if (verbose) {
+               printf("Loading...\n");
+       }
+
+       load_texture_image(target, fbo, tex, width, height,
+                          samples, valueScale);
+
+       if (verbose) {
+               printf("Validating...\n");
+       }
+
+       bool pass = validate_texture_image(target, intFormat, readbackProg, tex,
+                                          width, height, samples, valueScale);
+
+       if (!piglit_check_gl_error(GL_NO_ERROR)) {
+               pass = false;
+       }
+
+       piglit_report_result(pass ? PIGLIT_PASS : PIGLIT_FAIL);
+}
+
+
+enum piglit_result
+piglit_display(void)
+{
+       /* should never get here */
+       return PIGLIT_FAIL;
+}
-- 
1.9.1

_______________________________________________
Piglit mailing list
Piglit@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to