[Piglit] [PATCH piglit v2 1/6] Add a test case for all of the modes of RGBA_UNORM BPTC texture

Neil Roberts neil at linux.intel.com
Tue Jul 29 08:27:35 PDT 2014


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 <neil at linux.intel.com>
+ *
+ */
+
+/** @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



More information about the Piglit mailing list