This creates a compressed texture with a block for each of 8 modes of
RGBA_UNORM BPTC compression. The texture is then both rendered and
read back via glGetTexImage and compared with the expected values.
---
 tests/all.py                      |   1 +
 tests/texturing/CMakeLists.gl.txt |   1 +
 tests/texturing/bptc-modes.c      | 700 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 702 insertions(+)
 create mode 100644 tests/texturing/bptc-modes.c

diff --git a/tests/all.py b/tests/all.py
index 8b22f10..ed2d95e 100644
--- a/tests/all.py
+++ b/tests/all.py
@@ -2287,6 +2287,7 @@ arb_texture_compression['unknown formats'] = 
concurrent_test('arb_texture_compre
 arb_texture_compression_bptc = {}
 spec['ARB_texture_compression_bptc'] = arb_texture_compression_bptc
 arb_texture_compression_bptc['invalid formats'] = 
concurrent_test('arb_texture_compression-invalid-formats bptc')
+add_concurrent_test(arb_texture_compression_bptc, 'bptc-modes')
 
 ext_vertex_array_bgra = {}
 spec['EXT_vertex_array_bgra'] = ext_vertex_array_bgra
diff --git a/tests/texturing/CMakeLists.gl.txt 
b/tests/texturing/CMakeLists.gl.txt
index b121163..cd1bc11 100644
--- a/tests/texturing/CMakeLists.gl.txt
+++ b/tests/texturing/CMakeLists.gl.txt
@@ -13,6 +13,7 @@ link_libraries (
 piglit_add_executable (1-1-linear-texture 1-1-linear-texture.c)
 piglit_add_executable (array-depth-roundtrip array-depth-roundtrip.c)
 piglit_add_executable (array-texture array-texture.c)
+piglit_add_executable (bptc-modes bptc-modes.c)
 piglit_add_executable (compressedteximage compressedteximage.c)
 piglit_add_executable (copytexsubimage copytexsubimage.c)
 piglit_add_executable (copyteximage copyteximage.c)
diff --git a/tests/texturing/bptc-modes.c b/tests/texturing/bptc-modes.c
new file mode 100644
index 0000000..6a8b079
--- /dev/null
+++ b/tests/texturing/bptc-modes.c
@@ -0,0 +1,700 @@
+/*
+ * Copyright © 2014 Intel Corporation
+ *
+ * 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.
+ *
+ * Authors:
+ *    Neil Roberts <[email protected]>
+ *
+ */
+
+/** @file bptc-modes.c
+ *
+ * Tests BPTC-compressed RGBA_UNORM textures that with a block for
+ * each of the possible 8 modes. The texture is both rendered and
+ * retrieved with glGetTexImage and verified that it has the expected
+ * values.
+ */
+
+#include "piglit-util-gl.h"
+
+PIGLIT_GL_TEST_CONFIG_BEGIN
+
+       config.supports_gl_compat_version = 10;
+
+       config.window_visual = PIGLIT_GL_VISUAL_RGBA | PIGLIT_GL_VISUAL_DOUBLE;
+
+PIGLIT_GL_TEST_CONFIG_END
+
+#define BLOCK_SIZE 4
+#define BLOCK_BYTES 16
+#define N_PARTITIONS 64
+
+struct bptc_mode {
+   int n_subsets;
+   int n_partition_bits;
+   bool has_rotation_bits;
+   bool has_index_selection_bit;
+   int n_color_bits;
+   int n_alpha_bits;
+   bool has_endpoint_pbits;
+   bool has_shared_pbits;
+   int n_index_bits;
+   int n_secondary_index_bits;
+};
+
+static const struct bptc_mode
+bptc_modes[] = {
+   /* 0 */ { 3, 4, false, false, 4, 0, true,  false, 3, 0 },
+   /* 1 */ { 2, 6, false, false, 6, 0, false, true,  3, 0 },
+   /* 2 */ { 3, 6, false, false, 5, 0, false, false, 2, 0 },
+   /* 3 */ { 2, 6, false, false, 7, 0, true,  false, 2, 0 },
+   /* 4 */ { 1, 0, true,  true,  5, 6, false, false, 2, 3 },
+   /* 5 */ { 1, 0, true,  false, 7, 8, false, false, 2, 2 },
+   /* 6 */ { 1, 0, false, false, 7, 7, true,  false, 4, 0 },
+   /* 7 */ { 2, 6, false, false, 5, 5, true,  false, 2, 0 }
+};
+
+static const uint8_t
+anchor_indices[][N_PARTITIONS] = {
+   /* Anchor index values for the second subset of two-subset partitioning */
+   {
+      0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,
+      0xf,0x2,0x8,0x2,0x2,0x8,0x8,0xf,0x2,0x8,0x2,0x2,0x8,0x8,0x2,0x2,
+      0xf,0xf,0x6,0x8,0x2,0x8,0xf,0xf,0x2,0x8,0x2,0x2,0x2,0xf,0xf,0x6,
+      0x6,0x2,0x6,0x8,0xf,0xf,0x2,0x2,0xf,0xf,0xf,0xf,0xf,0x2,0x2,0xf
+   },
+
+   /* Anchor index values for the second subset of three-subset partitioning */
+   {
+      0x3,0x3,0xf,0xf,0x8,0x3,0xf,0xf,0x8,0x8,0x6,0x6,0x6,0x5,0x3,0x3,
+      0x3,0x3,0x8,0xf,0x3,0x3,0x6,0xa,0x5,0x8,0x8,0x6,0x8,0x5,0xf,0xf,
+      0x8,0xf,0x3,0x5,0x6,0xa,0x8,0xf,0xf,0x3,0xf,0x5,0xf,0xf,0xf,0xf,
+      0x3,0xf,0x5,0x5,0x5,0x8,0x5,0xa,0x5,0xa,0x8,0xd,0xf,0xc,0x3,0x3
+   },
+
+   /* Anchor index values for the third subset of three-subset
+    * partitioning
+    */
+   {
+      0xf,0x8,0x8,0x3,0xf,0xf,0x3,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,
+      0xf,0x8,0xf,0x3,0xf,0x8,0xf,0x8,0x3,0xf,0x6,0xa,0xf,0xf,0xa,0x8,
+      0xf,0x3,0xf,0xa,0xa,0x8,0x9,0xa,0x6,0xf,0x8,0xf,0x3,0x6,0x6,0x8,
+      0xf,0x3,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x3,0xf,0xf,0x8
+   }
+};
+
+struct bptc_block {
+       int mode;
+       int partition;
+       int rotation;
+       int index_selection;
+       uint8_t endpoints[2 * 3][4];
+       uint8_t pbits[3 * 2];
+       uint8_t primary_indices[BLOCK_SIZE * BLOCK_SIZE];
+       uint8_t secondary_indices[BLOCK_SIZE * BLOCK_SIZE];
+       uint8_t expected_values[BLOCK_SIZE * BLOCK_SIZE * 4];
+};
+
+static const struct bptc_block
+bptc_blocks[] = {
+       {
+               0, /* mode */
+               2, /* partition */
+               0, /* rotation (not used) */
+               0, /* index selection (not used) */
+               /* endpoints */
+               {
+                       /* #000000ff #ffffffff */
+                       { 0x0, 0x0, 0x0, 0x0 }, { 0xf, 0xf, 0xf, 0x0 },
+                       /* #100010ff #ef08efff */
+                       { 0x1, 0x0, 0x1, 0x0 }, { 0xe, 0x0, 0xe, 0x0 },
+                       /* #001010ff #08dedeff */
+                       { 0x0, 0x1, 0x1, 0x0 }, { 0x0, 0xd, 0xd, 0x0 }
+               },
+               /* pbits */
+               { 0, 1, 0, 1, 0, 1 },
+               /* primary indices */
+               {
+                       0x0, 0x2, 0x4, 0x7, /* subsets 0(a) 0    0    0    */
+                       0x0, 0x0, 0x7, 0x7, /* subsets 2    0    0    1    */
+                       0x0, 0x7, 0x0, 0x7, /* subsets 2(a) 2    1    1    */
+                       0x4, 0x2, 0x4, 0x2  /* subsets 2    2    1    1(a) */
+               },
+               /* secondary indices */
+               { },
+               /* expected results */
+               {
+                       0x00, 0x00, 0x00, 0xff, 0x48, 0x48, 0x48, 0xff,
+                       0x93, 0x93, 0x93, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0x00, 0x10, 0x10, 0xff, 0x00, 0x00, 0x00, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0xef, 0x08, 0xef, 0xff,
+                       0x00, 0x10, 0x10, 0xff, 0x08, 0xde, 0xde, 0xff,
+                       0x10, 0x00, 0x10, 0xff, 0xef, 0x08, 0xef, 0xff,
+                       0x05, 0x87, 0x87, 0xff, 0x02, 0x4a, 0x4a, 0xff,
+                       0x91, 0x05, 0x91, 0xff, 0x4f, 0x02, 0x4f, 0xff
+               },
+       },
+       {
+               1, /* mode */
+               63, /* partition */
+               0, /* rotation (not used) */
+               0, /* index selection (not used) */
+               /* endpoints */
+               {
+                       /* #000000ff #fdfdfdff */
+                       { 0x00, 0x00, 0x00, 0x00 }, { 0x3f, 0x3f, 0x3f, 0x00 },
+                       /* #060206ff #bb02bbff */
+                       { 0x01, 0x00, 0x01, 0x00 }, { 0x2e, 0x00, 0x2e, 0x00 },
+               },
+               /* pbits */
+               { 0, 1 },
+               /* primary indices */
+               {
+                       0x0, 0x2, 0x4, 0x7, /* subsets 0(a) 1    0    0    */
+                       0x0, 0x0, 0x7, 0x7, /* subsets 0    1    0    0    */
+                       0x0, 0x7, 0x0, 0x7, /* subsets 0    1    1    1    */
+                       0x4, 0x2, 0x4, 0x2  /* subsets 0    1    1    1(a) */
+               },
+               /* secondary indices */
+               { },
+               /* expected results */
+               {
+                       0x00, 0x00, 0x00, 0xff, 0x39, 0x02, 0x39, 0xff,
+                       0x92, 0x92, 0x92, 0xff, 0xfd, 0xfd, 0xfd, 0xff,
+                       0x00, 0x00, 0x00, 0xff, 0x06, 0x02, 0x06, 0xff,
+                       0xfd, 0xfd, 0xfd, 0xff, 0xfd, 0xfd, 0xfd, 0xff,
+                       0x00, 0x00, 0x00, 0xff, 0xbb, 0x02, 0xbb, 0xff,
+                       0x06, 0x02, 0x06, 0xff, 0xbb, 0x02, 0xbb, 0xff,
+                       0x92, 0x92, 0x92, 0xff, 0x39, 0x02, 0x39, 0xff,
+                       0x6f, 0x02, 0x6f, 0xff, 0x39, 0x02, 0x39, 0xff,
+               },
+       },
+       {
+               2, /* mode */
+               52, /* partition */
+               0, /* rotation (not used) */
+               0, /* index selection (not used) */
+               /* endpoints */
+               {
+                       /* #000000ff #ffffffff */
+                       { 0x00, 0x00, 0x00, 0x00 }, { 0x1f, 0x1f, 0x1f, 0x00 },
+                       /* #080008ff #730073ff */
+                       { 0x01, 0x00, 0x01, 0x00 }, { 0x0e, 0x00, 0x0e, 0x00 },
+                       /* #008484ff #006b6bff */
+                       { 0x00, 0x10, 0x10, 0x00 }, { 0x00, 0x0d, 0x0d, 0x00 }
+               },
+               /* pbits */
+               { },
+               /* primary indices */
+               {
+                       0x0, 0x0, 0x1, 0x2, /* subsets 0(a) 2    2    2    */
+                       0x1, 0x0, 0x1, 0x2, /* subsets 0    1(a) 1    1    */
+                       0x2, 0x3, 0x0, 0x0, /* subsets 0    1    1    1    */
+                       0x3, 0x3, 0x0, 0x0  /* subsets 0    2    2    2(a) */
+               },
+               /* secondary indices */
+               { },
+               /* expected results */
+               {
+                       0x00, 0x00, 0x00, 0xff, 0x00, 0x84, 0x84, 0xff,
+                       0x00, 0x7c, 0x7c, 0xff, 0x00, 0x73, 0x73, 0xff,
+                       0x54, 0x54, 0x54, 0xff, 0x08, 0x00, 0x08, 0xff,
+                       0x2b, 0x00, 0x2b, 0xff, 0x50, 0x00, 0x50, 0xff,
+                       0xab, 0xab, 0xab, 0xff, 0x73, 0x00, 0x73, 0xff,
+                       0x08, 0x00, 0x08, 0xff, 0x08, 0x00, 0x08, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0x00, 0x6b, 0x6b, 0xff,
+                       0x00, 0x84, 0x84, 0xff, 0x00, 0x84, 0x84, 0xff,
+               },
+       },
+       {
+               3, /* mode */
+               1, /* partition */
+               0, /* rotation (not used) */
+               0, /* index selection (not used) */
+               /* endpoints */
+               {
+                       /* #000000ff #ffffffff */
+                       { 0x00, 0x00, 0x00, 0x00 }, { 0x7f, 0x7f, 0x7f, 0x00 },
+                       /* #840084ff #e101e1ff */
+                       { 0x42, 0x00, 0x42, 0x00 }, { 0x70, 0x00, 0x70, 0x00 },
+               },
+               /* pbits */
+               { 0, 1, 0, 1 },
+               /* primary indices */
+               {
+                       0x0, 0x0, 0x0, 0x3, /* subsets 0(a) 0    0    1    */
+                       0x1, 0x1, 0x1, 0x2, /* subsets 0    0    0    1    */
+                       0x2, 0x2, 0x2, 0x1, /* subsets 0    0    0    1    */
+                       0x3, 0x3, 0x3, 0x0  /* subsets 0    0    0    1(a) */
+               },
+               /* secondary indices */
+               { },
+               /* expected results */
+               {
+                       0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
+                       0x00, 0x00, 0x00, 0xff, 0xe1, 0x01, 0xe1, 0xff,
+                       0x54, 0x54, 0x54, 0xff, 0x54, 0x54, 0x54, 0xff,
+                       0x54, 0x54, 0x54, 0xff, 0xc2, 0x01, 0xc2, 0xff,
+                       0xab, 0xab, 0xab, 0xff, 0xab, 0xab, 0xab, 0xff,
+                       0xab, 0xab, 0xab, 0xff, 0xa3, 0x00, 0xa3, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+                       0xff, 0xff, 0xff, 0xff, 0x84, 0x00, 0x84, 0xff,
+               },
+       },
+       {
+               4, /* mode */
+               0, /* partition (not used) */
+               1, /* rotation */
+               1, /* index selection */
+               /* endpoints */
+               {
+                       /* #007bff41 #ff7b00ff */
+                       { 0x00, 0x0f, 0x1f, 0x10 }, { 0x1f, 0x0f, 0x00, 0x3f },
+               },
+               /* pbits */
+               { },
+               /* primary indices */
+               {
+                       0x0, 0x1, 0x2, 0x3,
+                       0x0, 0x1, 0x2, 0x3,
+                       0x0, 0x1, 0x2, 0x3,
+                       0x0, 0x1, 0x2, 0x3
+               },
+               /* secondary indices */
+               {
+                       0x0, 0x1, 0x2, 0x3,
+                       0x4, 0x5, 0x6, 0x7,
+                       0x0, 0x1, 0x2, 0x3,
+                       0x4, 0x5, 0x6, 0x7
+               },
+               /* expected results */
+               {
+                       0x41, 0x7b, 0xff, 0x00, 0x7f, 0x7b, 0xdb, 0x24,
+                       0xc1, 0x7b, 0xb7, 0x48, 0xff, 0x7b, 0x93, 0x6c,
+                       0x41, 0x7b, 0x6c, 0x93, 0x7f, 0x7b, 0x48, 0xb7,
+                       0xc1, 0x7b, 0x24, 0xdb, 0xff, 0x7b, 0x00, 0xff,
+                       0x41, 0x7b, 0xff, 0x00, 0x7f, 0x7b, 0xdb, 0x24,
+                       0xc1, 0x7b, 0xb7, 0x48, 0xff, 0x7b, 0x93, 0x6c,
+                       0x41, 0x7b, 0x6c, 0x93, 0x7f, 0x7b, 0x48, 0xb7,
+                       0xc1, 0x7b, 0x24, 0xdb, 0xff, 0x7b, 0x00, 0xff,
+               },
+       },
+       {
+               5, /* mode */
+               0, /* partition (not used) */
+               3, /* rotation */
+               0, /* index selection (not used) */
+               /* endpoints */
+               {
+                       /* #0081ff10 #ff8100ff */
+                       { 0x00, 0x40, 0x7f, 0x10 }, { 0x7f, 0x40, 0x00, 0xff },
+               },
+               /* pbits */
+               { },
+               /* primary indices */
+               {
+                       0x0, 0x1, 0x2, 0x3,
+                       0x0, 0x1, 0x2, 0x3,
+                       0x0, 0x1, 0x2, 0x3,
+                       0x0, 0x1, 0x2, 0x3
+               },
+               /* secondary indices */
+               {
+                       0x0, 0x0, 0x0, 0x0,
+                       0x1, 0x1, 0x1, 0x1,
+                       0x2, 0x2, 0x2, 0x2,
+                       0x3, 0x3, 0x3, 0x3
+               },
+               /* expected results */
+               {
+                       0x00, 0x81, 0x10, 0xff, 0x54, 0x81, 0x10, 0xab,
+                       0xab, 0x81, 0x10, 0x54, 0xff, 0x81, 0x10, 0x00,
+                       0x00, 0x81, 0x5e, 0xff, 0x54, 0x81, 0x5e, 0xab,
+                       0xab, 0x81, 0x5e, 0x54, 0xff, 0x81, 0x5e, 0x00,
+                       0x00, 0x81, 0xb1, 0xff, 0x54, 0x81, 0xb1, 0xab,
+                       0xab, 0x81, 0xb1, 0x54, 0xff, 0x81, 0xb1, 0x00,
+                       0x00, 0x81, 0xff, 0xff, 0x54, 0x81, 0xff, 0xab,
+                       0xab, 0x81, 0xff, 0x54, 0xff, 0x81, 0xff, 0x00,
+               },
+       },
+       {
+               6, /* mode */
+               0, /* partition (not used) */
+               0, /* rotation (not used) */
+               0, /* index selection (not used) */
+               /* endpoints */
+               {
+                       /* #0181ff21 #fe8000fe */
+                       { 0x00, 0x40, 0x7f, 0x10 }, { 0x7f, 0x40, 0x00, 0x7f },
+               },
+               /* pbits */
+               { 1, 0 },
+               /* primary indices */
+               {
+                       0x0, 0x1, 0x2, 0x3,
+                       0x4, 0x5, 0x6, 0x7,
+                       0x8, 0x9, 0xa, 0xb,
+                       0xc, 0xd, 0xe, 0xf
+               },
+               /* secondary indices */
+               { },
+               /* expected results */
+               {
+                       0x01, 0x81, 0xff, 0x21, 0x11, 0x81, 0xef, 0x2f,
+                       0x25, 0x81, 0xdb, 0x40, 0x34, 0x81, 0xcb, 0x4e,
+                       0x44, 0x81, 0xbb, 0x5c, 0x54, 0x81, 0xab, 0x6a,
+                       0x68, 0x81, 0x97, 0x7b, 0x78, 0x81, 0x87, 0x89,
+                       0x87, 0x80, 0x78, 0x96, 0x97, 0x80, 0x68, 0xa4,
+                       0xab, 0x80, 0x54, 0xb5, 0xbb, 0x80, 0x44, 0xc3,
+                       0xcb, 0x80, 0x34, 0xd1, 0xda, 0x80, 0x24, 0xdf,
+                       0xee, 0x80, 0x10, 0xf0, 0xfe, 0x80, 0x00, 0xfe,
+               },
+       },
+       {
+               7, /* mode */
+               8, /* partition */
+               0, /* rotation (not used) */
+               0, /* index selection (not used) */
+               /* endpoints */
+               {
+                       /* #00000000 #ffffffff */
+                       { 0x00, 0x00, 0x00, 0x00 }, { 0x1f, 0x1f, 0x1f, 0x1f },
+                       /* #040c141c #fbf3ebe3 */
+                       { 0x00, 0x01, 0x02, 0x03 }, { 0x1f, 0x1e, 0x1d, 0x1c },
+               },
+               /* pbits */
+               { 0, 1, 1, 0 },
+               /* primary indices */
+               {
+                       0x0, 0x1, 0x2, 0x3, /* subsets 0(a) 0    0    0    */
+                       0x0, 0x1, 0x2, 0x3, /* subsets 0    0    0    0    */
+                       0x0, 0x1, 0x2, 0x3, /* subsets 0    0    0    1    */
+                       0x0, 0x1, 0x1, 0x0  /* subsets 0    0    1    1(a) */
+               },
+               /* secondary indices */
+               { },
+               /* expected results */
+               {
+                       0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x54, 0x54,
+                       0xab, 0xab, 0xab, 0xab, 0xff, 0xff, 0xff, 0xff,
+                       0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x54, 0x54,
+                       0xab, 0xab, 0xab, 0xab, 0xff, 0xff, 0xff, 0xff,
+                       0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x54, 0x54,
+                       0xab, 0xab, 0xab, 0xab, 0xfb, 0xf3, 0xeb, 0xe3,
+                       0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x54, 0x54,
+                       0x55, 0x58, 0x5b, 0x5d, 0x04, 0x0c, 0x14, 0x1c,
+               },
+       },
+};
+
+#define N_BLOCKS ARRAY_SIZE(bptc_blocks)
+
+static void
+write_bits(uint8_t *out,
+          int *offset,
+          int value,
+          int n_bits)
+{
+       int bit_index = *offset % 8;
+       int byte_index = *offset / 8;
+       int n_bits_in_byte = MIN2(n_bits, 8 - bit_index);
+
+       *offset += n_bits;
+
+       while (n_bits > 0) {
+               out[byte_index] |= ((value & ((1 << n_bits_in_byte) - 1)) <<
+                                   bit_index);
+
+               n_bits -= n_bits_in_byte;
+               value >>= n_bits_in_byte;
+               byte_index++;
+               bit_index = 0;
+               n_bits_in_byte = MIN2(n_bits, 8);
+       }
+}
+
+static void
+write_component(uint8_t *out,
+               int *offset,
+               const struct bptc_block *block,
+               int component, int subset, int endpoint)
+{
+       write_bits(out, offset,
+                  block->endpoints[subset * 2 + endpoint][component],
+                  bptc_modes[block->mode].n_color_bits);
+}
+
+static bool
+is_anchor(const struct bptc_block *block,
+          int texel)
+{
+       if (texel == 0)
+               return true;
+
+       switch (bptc_modes[block->mode].n_subsets) {
+       case 1:
+               return false;
+       case 2:
+               return anchor_indices[0][block->partition] == texel;
+       case 3:
+               return (anchor_indices[1][block->partition] == texel ||
+                       anchor_indices[2][block->partition] == texel);
+       default:
+               assert(false);
+               return false;
+       }
+}
+
+static void
+make_block(const struct bptc_block *block,
+          uint8_t *out)
+{
+       const struct bptc_mode *mode = bptc_modes + block->mode;
+       int offset = 0;
+       int component;
+       int subset;
+       int endpoint;
+       int n_bits;
+       int i;
+
+       memset(out, 0, BLOCK_SIZE * BLOCK_SIZE);
+
+       write_bits(out, &offset, 1 << block->mode, block->mode + 1);
+
+       write_bits(out, &offset, block->partition, mode->n_partition_bits);
+
+       write_bits(out, &offset, block->rotation,
+                  mode->has_rotation_bits ? 2 : 0);
+
+       write_bits(out, &offset, block->index_selection,
+                  mode->has_index_selection_bit);
+
+       for (component = 0; component < 3; component++) {
+               for (subset = 0; subset < mode->n_subsets; subset++) {
+                       for (endpoint = 0; endpoint < 2; endpoint++) {
+                               write_component(out, &offset, block,
+                                               component, subset, endpoint);
+                       }
+               }
+       }
+
+       for (subset = 0; subset < mode->n_subsets; subset++) {
+               for (endpoint = 0; endpoint < 2; endpoint++) {
+                       write_bits(out, &offset,
+                                  block->endpoints[subset * 2 + endpoint][3],
+                                  mode->n_alpha_bits);
+               }
+       }
+
+       for (subset = 0; subset < mode->n_subsets; subset++) {
+               for (endpoint = 0; endpoint < 2; endpoint++) {
+                       write_bits(out, &offset,
+                                  block->pbits[subset * 2 + endpoint],
+                                  mode->has_endpoint_pbits);
+               }
+       }
+
+       for (subset = 0; subset < mode->n_subsets; subset++) {
+               write_bits(out, &offset,
+                          block->pbits[subset],
+                          mode->has_shared_pbits);
+       }
+
+       for (i = 0; i < BLOCK_SIZE * BLOCK_SIZE; i++) {
+               n_bits = mode->n_index_bits;
+
+               if (is_anchor(block, i))
+                       n_bits--;
+
+               write_bits(out, &offset, block->primary_indices[i], n_bits);
+       }
+
+       if (mode->n_secondary_index_bits) {
+               for (i = 0; i < BLOCK_SIZE * BLOCK_SIZE; i++) {
+                       n_bits = mode->n_secondary_index_bits;
+
+                       if (is_anchor(block, i))
+                               n_bits--;
+
+                       write_bits(out, &offset,
+                                  block->secondary_indices[i], n_bits);
+               }
+       }
+
+       assert(offset == BLOCK_BYTES * 8);
+}
+
+static GLuint
+make_tex(void)
+{
+       GLuint tex;
+       uint8_t data[BLOCK_BYTES * N_BLOCKS];
+       int i;
+
+       glGenTextures(1, &tex);
+       glBindTexture(GL_TEXTURE_2D, tex);
+
+       for (i = 0; i < N_BLOCKS; i++)
+               make_block(bptc_blocks + i, data + i * BLOCK_BYTES);
+
+       glCompressedTexImage2D(GL_TEXTURE_2D,
+                              0, /* level */
+                              GL_COMPRESSED_RGBA_BPTC_UNORM_ARB,
+                              BLOCK_SIZE * 2, BLOCK_SIZE * N_BLOCKS / 2,
+                              0, /* border */
+                              sizeof data,
+                              data);
+
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+       glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+
+       return tex;
+}
+
+static bool
+compare_results(const uint8_t *expected,
+               const uint8_t *observed,
+               int observed_rowstride)
+{
+       int y, x;
+
+       for (y = 0; y < BLOCK_SIZE; y++) {
+               for (x = 0; x < BLOCK_SIZE; x++) {
+                       if (memcmp(expected, observed, 4)) {
+                               printf("Unexpected color at %i,%i:\n"
+                                      "  expected %02x%02x%02x%02x\n"
+                                      "  observed %02x%02x%02x%02x\n",
+                                      x, y,
+                                      expected[0], expected[1],
+                                      expected[2], expected[3],
+                                      observed[0], observed[1],
+                                      observed[2], observed[3]);
+                               return false;
+                       }
+                       expected += 4;
+                       observed += 4;
+               }
+
+               observed += observed_rowstride - 4 * BLOCK_SIZE;
+       }
+
+       return true;
+}
+
+static void
+render_texture(uint8_t *render_data,
+              uint8_t *get_data)
+{
+       GLuint tex;
+
+       tex = make_tex();
+
+       glBindTexture(GL_TEXTURE_2D, tex);
+       glEnable(GL_TEXTURE_2D);
+
+       piglit_draw_rect_tex(0, 0, BLOCK_SIZE * 2, BLOCK_SIZE * N_BLOCKS / 2,
+                            0.0f, 0.0f, 1.0f, 1.0f);
+
+       glDisable(GL_TEXTURE_2D);
+       glPixelStorei(GL_PACK_ALIGNMENT, 1);
+       glReadPixels(0, 0, BLOCK_SIZE * 2, BLOCK_SIZE * N_BLOCKS / 2,
+                    GL_RGBA, GL_UNSIGNED_BYTE, render_data);
+
+       glGetTexImage(GL_TEXTURE_2D,
+                     0, /* level */
+                     GL_RGBA,
+                     GL_UNSIGNED_BYTE,
+                     get_data);
+
+       glBindTexture(GL_TEXTURE_2D, 0);
+       glDeleteTextures(1, &tex);
+}
+
+static GLboolean
+check_block(const struct bptc_block *block,
+           const uint8_t *render_data,
+           const uint8_t *get_data)
+{
+       GLboolean overall_result = GL_TRUE;
+       GLboolean pass;
+
+       printf("mode %i, partition %i, rotation %i, index %i\n",
+              block->mode,
+              block->partition,
+              block->rotation,
+              block->index_selection);
+
+       pass = compare_results(block->expected_values,
+                              render_data,
+                              BLOCK_SIZE * 2 * 4);
+       printf("render: %s\n", pass ? "pass" : "fail");
+
+       overall_result &= pass;
+
+       pass = compare_results(block->expected_values,
+                              get_data,
+                              BLOCK_SIZE * 2 * 4);
+       printf("glGetTexImage: %s\n", pass ? "pass" : "fail");
+
+       overall_result &= pass;
+
+       return overall_result;
+}
+
+enum piglit_result
+piglit_display(void)
+{
+       GLboolean pass = GL_TRUE;
+       uint8_t render_data[BLOCK_SIZE * BLOCK_SIZE * N_BLOCKS * 4];
+       uint8_t get_data[BLOCK_SIZE * BLOCK_SIZE * N_BLOCKS * 4];
+       int offset;
+       int i;
+
+       glClearColor(0, 0, 0, 0);
+       glClear(GL_COLOR_BUFFER_BIT);
+
+       render_texture(render_data, get_data);
+
+       for (i = 0; i < N_BLOCKS; i++) {
+               offset = (i % 2 * BLOCK_SIZE * 4 +
+                         i / 2 * BLOCK_SIZE * BLOCK_SIZE * 2 * 4);
+               pass &= check_block(bptc_blocks + i,
+                                   render_data + offset,
+                                   get_data + offset);
+       }
+
+       piglit_present_results();
+
+       return pass ? PIGLIT_PASS : PIGLIT_FAIL;
+}
+
+void
+piglit_init(int argc, char **argv)
+{
+       if (piglit_get_gl_version() < 42 &&
+           !piglit_is_extension_supported("GL_ARB_texture_compression_bptc")) {
+               printf("OpenGL 4.2 or GL_ARB_texture_compression_bptc "
+                      "is required.\n");
+               piglit_report_result(PIGLIT_SKIP);
+       }
+
+       piglit_ortho_projection(piglit_width, piglit_height, GL_FALSE);
+}
-- 
1.9.3

_______________________________________________
Piglit mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/piglit

Reply via email to