/* * 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 * */ /** @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; config.khr_no_error_support = PIGLIT_NO_ERRORS; 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 */ { 0 }, /* 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 */ { 0 }, /* 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 */ { 0 }, /* 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 */ { 0 }, /* 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 */ { 0 }, /* 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 */ { 0 }, /* 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 */ { 0 }, /* 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 */ { 0 }, /* 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 */ { 0 }, /* 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); }