-#define BLOCK_SIZE 4
-#define N_PARTITIONS 64
-#define BLOCK_BYTES 16
-
-struct bptc_unorm_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;
-};
-
-struct bptc_float_bitfield {
- int8_t endpoint;
- uint8_t component;
- uint8_t offset;
- uint8_t n_bits;
- bool reverse;
-};
-
-struct bptc_float_mode {
- bool reserved;
- bool transformed_endpoints;
- int n_partition_bits;
- int n_endpoint_bits;
- int n_index_bits;
- int n_delta_bits[3];
- struct bptc_float_bitfield bitfields[24];
-};
-
-struct bit_writer {
- uint8_t buf;
- int pos;
- uint8_t *dst;
-};
-
-static const struct bptc_unorm_mode
-bptc_unorm_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 struct bptc_float_mode
-bptc_float_modes[] = {
- /* 00 */
- { false, true, 5, 10, 3, { 5, 5, 5 },
- { { 2, 1, 4, 1, false }, { 2, 2, 4, 1, false }, { 3, 2, 4, 1, false },
- { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
- { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
- { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
- { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
- { 3, 2, 3, 1, false },
- { -1 } }
- },
- /* 01 */
- { false, true, 5, 7, 3, { 6, 6, 6 },
- { { 2, 1, 5, 1, false }, { 3, 1, 4, 1, false }, { 3, 1, 5, 1, false },
- { 0, 0, 0, 7, false }, { 3, 2, 0, 1, false }, { 3, 2, 1, 1, false },
- { 2, 2, 4, 1, false }, { 0, 1, 0, 7, false }, { 2, 2, 5, 1, false },
- { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false }, { 0, 2, 0, 7, false },
- { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
- { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
- { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
- { 2, 0, 0, 6, false },
- { 3, 0, 0, 6, false },
- { -1 } }
- },
- /* 00010 */
- { false, true, 5, 11, 3, { 5, 4, 4 },
- { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 5, false }, { 0, 0, 10, 1, false }, { 2, 1, 0, 4, false },
- { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false }, { 3, 2, 0, 1, false },
- { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
- { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
- { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
- { -1 } }
- },
- /* 00011 */
- { false, false, 0, 10, 4, { 10, 10, 10 },
- { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 10, false }, { 1, 1, 0, 10, false }, { 1, 2, 0, 10, false },
- { -1 } }
- },
- /* 00110 */
- { false, true, 5, 11, 3, { 4, 5, 4 },
- { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 3, 1, 4, 1, false },
- { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false }, { 0, 1, 10, 1, false },
- { 3, 1, 0, 4, false }, { 1, 2, 0, 4, false }, { 0, 2, 10, 1, false },
- { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
- { 3, 2, 0, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
- { 2, 1, 4, 1, false }, { 3, 2, 3, 1, false },
- { -1 } }
- },
- /* 00111 */
- { false, true, 0, 11, 4, { 9, 9, 9 },
- { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 9, false }, { 0, 0, 10, 1, false }, { 1, 1, 0, 9, false },
- { 0, 1, 10, 1, false }, { 1, 2, 0, 9, false }, { 0, 2, 10, 1, false },
- { -1 } }
- },
- /* 01010 */
- { false, true, 5, 11, 3, { 4, 4, 5 },
- { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 4, false }, { 0, 0, 10, 1, false }, { 2, 2, 4, 1, false },
- { 2, 1, 0, 4, false }, { 1, 1, 0, 4, false }, { 0, 1, 10, 1, false },
- { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
- { 0, 2, 10, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 4, false },
- { 3, 2, 1, 1, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 4, false },
- { 3, 2, 4, 1, false }, { 3, 2, 3, 1, false },
- { -1 } }
- },
- /* 01011 */
- { false, true, 0, 12, 4, { 8, 8, 8 },
- { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 8, false }, { 0, 0, 10, 2, true }, { 1, 1, 0, 8, false },
- { 0, 1, 10, 2, true }, { 1, 2, 0, 8, false }, { 0, 2, 10, 2, true },
- { -1 } }
- },
- /* 01110 */
- { false, true, 5, 9, 3, { 5, 5, 5 },
- { { 0, 0, 0, 9, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 9, false },
- { 2, 1, 4, 1, false }, { 0, 2, 0, 9, false }, { 3, 2, 4, 1, false },
- { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
- { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
- { 1, 2, 0, 5, false }, { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false },
- { 2, 0, 0, 5, false }, { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false },
- { 3, 2, 3, 1, false },
- { -1 } }
- },
- /* 01111 */
- { false, true, 0, 16, 4, { 4, 4, 4 },
- { { 0, 0, 0, 10, false }, { 0, 1, 0, 10, false }, { 0, 2, 0, 10, false },
- { 1, 0, 0, 4, false }, { 0, 0, 10, 6, true }, { 1, 1, 0, 4, false },
- { 0, 1, 10, 6, true }, { 1, 2, 0, 4, false }, { 0, 2, 10, 6, true },
- { -1 } }
- },
- /* 10010 */
- { false, true, 5, 8, 3, { 6, 5, 5 },
- { { 0, 0, 0, 8, false }, { 3, 1, 4, 1, false }, { 2, 2, 4, 1, false },
- { 0, 1, 0, 8, false }, { 3, 2, 2, 1, false }, { 2, 1, 4, 1, false },
- { 0, 2, 0, 8, false }, { 3, 2, 3, 1, false }, { 3, 2, 4, 1, false },
- { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 5, false },
- { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
- { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 6, false },
- { 3, 0, 0, 6, false },
- { -1 } }
- },
- /* 10011 */
- { true /* reserved */ },
- /* 10110 */
- { false, true, 5, 8, 3, { 5, 6, 5 },
- { { 0, 0, 0, 8, false }, { 3, 2, 0, 1, false }, { 2, 2, 4, 1, false },
- { 0, 1, 0, 8, false }, { 2, 1, 5, 1, false }, { 2, 1, 4, 1, false },
- { 0, 2, 0, 8, false }, { 3, 1, 5, 1, false }, { 3, 2, 4, 1, false },
- { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
- { 1, 1, 0, 6, false }, { 3, 1, 0, 4, false }, { 1, 2, 0, 5, false },
- { 3, 2, 1, 1, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
- { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
- { -1 } }
- },
- /* 10111 */
- { true /* reserved */ },
- /* 11010 */
- { false, true, 5, 8, 3, { 5, 5, 6 },
- { { 0, 0, 0, 8, false }, { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false },
- { 0, 1, 0, 8, false }, { 2, 2, 5, 1, false }, { 2, 1, 4, 1, false },
- { 0, 2, 0, 8, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
- { 1, 0, 0, 5, false }, { 3, 1, 4, 1, false }, { 2, 1, 0, 4, false },
- { 1, 1, 0, 5, false }, { 3, 2, 0, 1, false }, { 3, 1, 0, 4, false },
- { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false }, { 2, 0, 0, 5, false },
- { 3, 2, 2, 1, false }, { 3, 0, 0, 5, false }, { 3, 2, 3, 1, false },
- { -1 } }
- },
- /* 11011 */
- { true /* reserved */ },
- /* 11110 */
- { false, false, 5, 6, 3, { 6, 6, 6 },
- { { 0, 0, 0, 6, false }, { 3, 1, 4, 1, false }, { 3, 2, 0, 1, false },
- { 3, 2, 1, 1, false }, { 2, 2, 4, 1, false }, { 0, 1, 0, 6, false },
- { 2, 1, 5, 1, false }, { 2, 2, 5, 1, false }, { 3, 2, 2, 1, false },
- { 2, 1, 4, 1, false }, { 0, 2, 0, 6, false }, { 3, 1, 5, 1, false },
- { 3, 2, 3, 1, false }, { 3, 2, 5, 1, false }, { 3, 2, 4, 1, false },
- { 1, 0, 0, 6, false }, { 2, 1, 0, 4, false }, { 1, 1, 0, 6, false },
- { 3, 1, 0, 4, false }, { 1, 2, 0, 6, false }, { 2, 2, 0, 4, false },
- { 2, 0, 0, 6, false }, { 3, 0, 0, 6, false },
- { -1 } }
- },
- /* 11111 */
- { true /* reserved */ },
-};
-
-/* This partition table is used when the mode has two subsets. Each
- * partition is represented by a 32-bit value which gives 2 bits per texel
- * within the block. The value of the two bits represents which subset to use
- * (0 or 1).
- */
-static const uint32_t
-partition_table1[N_PARTITIONS] = {
- 0x50505050U, 0x40404040U, 0x54545454U, 0x54505040U,
- 0x50404000U, 0x55545450U, 0x55545040U, 0x54504000U,
- 0x50400000U, 0x55555450U, 0x55544000U, 0x54400000U,
- 0x55555440U, 0x55550000U, 0x55555500U, 0x55000000U,
- 0x55150100U, 0x00004054U, 0x15010000U, 0x00405054U,
- 0x00004050U, 0x15050100U, 0x05010000U, 0x40505054U,
- 0x00404050U, 0x05010100U, 0x14141414U, 0x05141450U,
- 0x01155440U, 0x00555500U, 0x15014054U, 0x05414150U,
- 0x44444444U, 0x55005500U, 0x11441144U, 0x05055050U,
- 0x05500550U, 0x11114444U, 0x41144114U, 0x44111144U,
- 0x15055054U, 0x01055040U, 0x05041050U, 0x05455150U,
- 0x14414114U, 0x50050550U, 0x41411414U, 0x00141400U,
- 0x00041504U, 0x00105410U, 0x10541000U, 0x04150400U,
- 0x50410514U, 0x41051450U, 0x05415014U, 0x14054150U,
- 0x41050514U, 0x41505014U, 0x40011554U, 0x54150140U,
- 0x50505500U, 0x00555050U, 0x15151010U, 0x54540404U,
-};
-
-/* This partition table is used when the mode has three subsets. In this case
- * the values can be 0, 1 or 2.
- */
-static const uint32_t
-partition_table2[N_PARTITIONS] = {
- 0xaa685050U, 0x6a5a5040U, 0x5a5a4200U, 0x5450a0a8U,
- 0xa5a50000U, 0xa0a05050U, 0x5555a0a0U, 0x5a5a5050U,
- 0xaa550000U, 0xaa555500U, 0xaaaa5500U, 0x90909090U,
- 0x94949494U, 0xa4a4a4a4U, 0xa9a59450U, 0x2a0a4250U,
- 0xa5945040U, 0x0a425054U, 0xa5a5a500U, 0x55a0a0a0U,
- 0xa8a85454U, 0x6a6a4040U, 0xa4a45000U, 0x1a1a0500U,
- 0x0050a4a4U, 0xaaa59090U, 0x14696914U, 0x69691400U,
- 0xa08585a0U, 0xaa821414U, 0x50a4a450U, 0x6a5a0200U,
- 0xa9a58000U, 0x5090a0a8U, 0xa8a09050U, 0x24242424U,
- 0x00aa5500U, 0x24924924U, 0x24499224U, 0x50a50a50U,
- 0x500aa550U, 0xaaaa4444U, 0x66660000U, 0xa5a0a5a0U,
- 0x50a050a0U, 0x69286928U, 0x44aaaa44U, 0x66666600U,
- 0xaa444444U, 0x54a854a8U, 0x95809580U, 0x96969600U,
- 0xa85454a8U, 0x80959580U, 0xaa141414U, 0x96960000U,
- 0xaaaa1414U, 0xa05050a0U, 0xa0a5a5a0U, 0x96000000U,
- 0x40804080U, 0xa9a8a9a8U, 0xaaaaaa44U, 0x2a4a5254U
-};
-
-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
- }
-};
-
-static int
-extract_bits(const uint8_t *block,
- int offset,
- int n_bits)
-{
- int byte_index = offset / 8;
- int bit_index = offset % 8;
- int n_bits_in_byte = MIN2(n_bits, 8 - bit_index);
- int result = 0;
- int bit = 0;
-
- while (true) {
- result |= ((block[byte_index] >> bit_index) &
- ((1 << n_bits_in_byte) - 1)) << bit;
-
- n_bits -= n_bits_in_byte;
-
- if (n_bits <= 0)
- return result;
-
- bit += n_bits_in_byte;
- byte_index++;
- bit_index = 0;
- n_bits_in_byte = MIN2(n_bits, 8);
- }
-}
-
-static uint8_t
-expand_component(uint8_t byte,
- int n_bits)
-{
- /* Expands a n-bit quantity into a byte by copying the most-significant
- * bits into the unused least-significant bits.
- */
- return byte << (8 - n_bits) | (byte >> (2 * n_bits - 8));
-}
-
-static int
-extract_unorm_endpoints(const struct bptc_unorm_mode *mode,
- const uint8_t *block,
- int bit_offset,
- uint8_t endpoints[][4])
-{
- int component;
- int subset;
- int endpoint;
- int pbit;
- int n_components;
-
- /* Extract each color component */
- for (component = 0; component < 3; component++) {
- for (subset = 0; subset < mode->n_subsets; subset++) {
- for (endpoint = 0; endpoint < 2; endpoint++) {
- endpoints[subset * 2 + endpoint][component] =
- extract_bits(block, bit_offset, mode->n_color_bits);
- bit_offset += mode->n_color_bits;
- }
- }
- }
-
- /* Extract the alpha values */
- if (mode->n_alpha_bits > 0) {
- for (subset = 0; subset < mode->n_subsets; subset++) {
- for (endpoint = 0; endpoint < 2; endpoint++) {
- endpoints[subset * 2 + endpoint][3] =
- extract_bits(block, bit_offset, mode->n_alpha_bits);
- bit_offset += mode->n_alpha_bits;
- }
- }
-
- n_components = 4;
- } else {
- for (subset = 0; subset < mode->n_subsets; subset++)
- for (endpoint = 0; endpoint < 2; endpoint++)
- endpoints[subset * 2 + endpoint][3] = 255;
-
- n_components = 3;
- }
-
- /* Add in the p-bits */
- if (mode->has_endpoint_pbits) {
- for (subset = 0; subset < mode->n_subsets; subset++) {
- for (endpoint = 0; endpoint < 2; endpoint++) {
- pbit = extract_bits(block, bit_offset, 1);
- bit_offset += 1;
-
- for (component = 0; component < n_components; component++) {
- endpoints[subset * 2 + endpoint][component] <<= 1;
- endpoints[subset * 2 + endpoint][component] |= pbit;
- }
- }
- }
- } else if (mode->has_shared_pbits) {
- for (subset = 0; subset < mode->n_subsets; subset++) {
- pbit = extract_bits(block, bit_offset, 1);
- bit_offset += 1;
-
- for (endpoint = 0; endpoint < 2; endpoint++) {
- for (component = 0; component < n_components; component++) {
- endpoints[subset * 2 + endpoint][component] <<= 1;
- endpoints[subset * 2 + endpoint][component] |= pbit;
- }
- }
- }
- }
-
- /* Expand the n-bit values to a byte */
- for (subset = 0; subset < mode->n_subsets; subset++) {
- for (endpoint = 0; endpoint < 2; endpoint++) {
- for (component = 0; component < 3; component++) {
- endpoints[subset * 2 + endpoint][component] =
- expand_component(endpoints[subset * 2 + endpoint][component],
- mode->n_color_bits +
- mode->has_endpoint_pbits +
- mode->has_shared_pbits);
- }
-
- if (mode->n_alpha_bits > 0) {
- endpoints[subset * 2 + endpoint][3] =
- expand_component(endpoints[subset * 2 + endpoint][3],
- mode->n_alpha_bits +
- mode->has_endpoint_pbits +
- mode->has_shared_pbits);
- }
- }
- }
-
- return bit_offset;
-}
-
-static bool
-is_anchor(int n_subsets,
- int partition_num,
- int texel)
-{
- if (texel == 0)
- return true;
-
- switch (n_subsets) {
- case 1:
- return false;
- case 2:
- return anchor_indices[0][partition_num] == texel;
- case 3:
- return (anchor_indices[1][partition_num] == texel ||
- anchor_indices[2][partition_num] == texel);
- default:
- assert(false);
- return false;
- }
-}
-
-static int
-count_anchors_before_texel(int n_subsets,
- int partition_num,
- int texel)
-{
- int count = 1;
-
- if (texel == 0)
- return 0;
-
- switch (n_subsets) {
- case 1:
- break;
- case 2:
- if (texel > anchor_indices[0][partition_num])
- count++;
- break;
- case 3:
- if (texel > anchor_indices[1][partition_num])
- count++;
- if (texel > anchor_indices[2][partition_num])
- count++;
- break;
- default:
- assert(false);
- return 0;
- }
-
- return count;
-}
-
-static int32_t
-interpolate(int32_t a, int32_t b,
- int index,
- int index_bits)