|
|
|
@@ -0,0 +1,960 @@
|
|
|
|
|
/*
|
|
|
|
|
* Copyright (C) 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.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* \file texcompress_bptc.c
|
|
|
|
|
* GL_ARB_texture_compression_bptc support.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdbool.h>
|
|
|
|
|
#include "texcompress.h"
|
|
|
|
|
#include "texcompress_bptc.h"
|
|
|
|
|
#include "util/format_srgb.h"
|
|
|
|
|
#include "texstore.h"
|
|
|
|
|
#include "macros.h"
|
|
|
|
|
#include "image.h"
|
|
|
|
|
|
|
|
|
|
#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];
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
static const uint8_t weights2[] = { 0, 21, 43, 64 };
|
|
|
|
|
static const uint8_t weights3[] = { 0, 9, 18, 27, 37, 46, 55, 64 };
|
|
|
|
|
static const uint8_t weights4[] =
|
|
|
|
|
{ 0, 4, 9, 13, 17, 21, 26, 30, 34, 38, 43, 47, 51, 55, 60, 64 };
|
|
|
|
|
static const uint8_t *weights[] = {
|
|
|
|
|
NULL, NULL, weights2, weights3, weights4
|
|
|
|
|
};
|
|
|
|
|
int weight;
|
|
|
|
|
|
|
|
|
|
weight = weights[index_bits][index];
|
|
|
|
|
|
|
|
|
|
return ((64 - weight) * a + weight * b + 32) >> 6;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
apply_rotation(int rotation,
|
|
|
|
|
uint8_t *result)
|
|
|
|
|
{
|
|
|
|
|
uint8_t t;
|
|
|
|
|
|
|
|
|
|
if (rotation == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
rotation--;
|
|
|
|
|
|
|
|
|
|
t = result[rotation];
|
|
|
|
|
result[rotation] = result[3];
|
|
|
|
|
result[3] = t;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_rgba_unorm_from_block(const uint8_t *block,
|
|
|
|
|
uint8_t *result,
|
|
|
|
|
int texel)
|
|
|
|
|
{
|
|
|
|
|
int mode_num = ffs(block[0]);
|
|
|
|
|
const struct bptc_unorm_mode *mode;
|
|
|
|
|
int bit_offset, secondary_bit_offset;
|
|
|
|
|
int partition_num;
|
|
|
|
|
int subset_num;
|
|
|
|
|
int rotation;
|
|
|
|
|
int index_selection;
|
|
|
|
|
int index_bits;
|
|
|
|
|
int indices[2];
|
|
|
|
|
int index;
|
|
|
|
|
int anchors_before_texel;
|
|
|
|
|
bool anchor;
|
|
|
|
|
uint8_t endpoints[3 * 2][4];
|
|
|
|
|
uint32_t subsets;
|
|
|
|
|
int component;
|
|
|
|
|
|
|
|
|
|
if (mode_num == 0) {
|
|
|
|
|
/* According to the spec this mode is reserved and shouldn't be used. */
|
|
|
|
|
memset(result, 0, 3);
|
|
|
|
|
result[3] = 0xff;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mode = bptc_unorm_modes + mode_num - 1;
|
|
|
|
|
bit_offset = mode_num;
|
|
|
|
|
|
|
|
|
|
partition_num = extract_bits(block, bit_offset, mode->n_partition_bits);
|
|
|
|
|
bit_offset += mode->n_partition_bits;
|
|
|
|
|
|
|
|
|
|
switch (mode->n_subsets) {
|
|
|
|
|
case 1:
|
|
|
|
|
subsets = 0;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
subsets = partition_table1[partition_num];
|
|
|
|
|
break;
|
|
|
|
|
case 3:
|
|
|
|
|
subsets = partition_table2[partition_num];
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
assert(false);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode->has_rotation_bits) {
|
|
|
|
|
rotation = extract_bits(block, bit_offset, 2);
|
|
|
|
|
bit_offset += 2;
|
|
|
|
|
} else {
|
|
|
|
|
rotation = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode->has_index_selection_bit) {
|
|
|
|
|
index_selection = extract_bits(block, bit_offset, 1);
|
|
|
|
|
bit_offset++;
|
|
|
|
|
} else {
|
|
|
|
|
index_selection = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bit_offset = extract_unorm_endpoints(mode, block, bit_offset, endpoints);
|
|
|
|
|
|
|
|
|
|
anchors_before_texel = count_anchors_before_texel(mode->n_subsets,
|
|
|
|
|
partition_num, texel);
|
|
|
|
|
|
|
|
|
|
/* Calculate the offset to the secondary index */
|
|
|
|
|
secondary_bit_offset = (bit_offset +
|
|
|
|
|
BLOCK_SIZE * BLOCK_SIZE * mode->n_index_bits -
|
|
|
|
|
mode->n_subsets +
|
|
|
|
|
mode->n_secondary_index_bits * texel -
|
|
|
|
|
anchors_before_texel);
|
|
|
|
|
|
|
|
|
|
/* Calculate the offset to the primary index for this texel */
|
|
|
|
|
bit_offset += mode->n_index_bits * texel - anchors_before_texel;
|
|
|
|
|
|
|
|
|
|
subset_num = (subsets >> (texel * 2)) & 3;
|
|
|
|
|
|
|
|
|
|
anchor = is_anchor(mode->n_subsets, partition_num, texel);
|
|
|
|
|
|
|
|
|
|
index_bits = mode->n_index_bits;
|
|
|
|
|
if (anchor)
|
|
|
|
|
index_bits--;
|
|
|
|
|
indices[0] = extract_bits(block, bit_offset, index_bits);
|
|
|
|
|
|
|
|
|
|
if (mode->n_secondary_index_bits) {
|
|
|
|
|
index_bits = mode->n_secondary_index_bits;
|
|
|
|
|
if (anchor)
|
|
|
|
|
index_bits--;
|
|
|
|
|
indices[1] = extract_bits(block, secondary_bit_offset, index_bits);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
index = indices[index_selection];
|
|
|
|
|
index_bits = (index_selection ?
|
|
|
|
|
mode->n_secondary_index_bits :
|
|
|
|
|
mode->n_index_bits);
|
|
|
|
|
|
|
|
|
|
for (component = 0; component < 3; component++)
|
|
|
|
|
result[component] = interpolate(endpoints[subset_num * 2][component],
|
|
|
|
|
endpoints[subset_num * 2 + 1][component],
|
|
|
|
|
index,
|
|
|
|
|
index_bits);
|
|
|
|
|
|
|
|
|
|
/* Alpha uses the opposite index from the color components */
|
|
|
|
|
if (mode->n_secondary_index_bits && !index_selection) {
|
|
|
|
|
index = indices[1];
|
|
|
|
|
index_bits = mode->n_secondary_index_bits;
|
|
|
|
|
} else {
|
|
|
|
|
index = indices[0];
|
|
|
|
|
index_bits = mode->n_index_bits;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result[3] = interpolate(endpoints[subset_num * 2][3],
|
|
|
|
|
endpoints[subset_num * 2 + 1][3],
|
|
|
|
|
index,
|
|
|
|
|
index_bits);
|
|
|
|
|
|
|
|
|
|
apply_rotation(rotation, result);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_bptc_rgba_unorm_bytes(const GLubyte *map,
|
|
|
|
|
GLint rowStride, GLint i, GLint j,
|
|
|
|
|
GLubyte *texel)
|
|
|
|
|
{
|
|
|
|
|
const GLubyte *block;
|
|
|
|
|
|
|
|
|
|
block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
|
|
|
|
|
|
|
|
|
|
fetch_rgba_unorm_from_block(block, texel, (i % 4) + (j % 4) * 4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_bptc_rgba_unorm(const GLubyte *map,
|
|
|
|
|
GLint rowStride, GLint i, GLint j,
|
|
|
|
|
GLfloat *texel)
|
|
|
|
|
{
|
|
|
|
|
GLubyte texel_bytes[4];
|
|
|
|
|
|
|
|
|
|
fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
|
|
|
|
|
|
|
|
|
|
texel[RCOMP] = UBYTE_TO_FLOAT(texel_bytes[0]);
|
|
|
|
|
texel[GCOMP] = UBYTE_TO_FLOAT(texel_bytes[1]);
|
|
|
|
|
texel[BCOMP] = UBYTE_TO_FLOAT(texel_bytes[2]);
|
|
|
|
|
texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_bptc_srgb_alpha_unorm(const GLubyte *map,
|
|
|
|
|
GLint rowStride, GLint i, GLint j,
|
|
|
|
|
GLfloat *texel)
|
|
|
|
|
{
|
|
|
|
|
GLubyte texel_bytes[4];
|
|
|
|
|
|
|
|
|
|
fetch_bptc_rgba_unorm_bytes(map, rowStride, i, j, texel_bytes);
|
|
|
|
|
|
|
|
|
|
texel[RCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[0]);
|
|
|
|
|
texel[GCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[1]);
|
|
|
|
|
texel[BCOMP] = util_format_srgb_8unorm_to_linear_float(texel_bytes[2]);
|
|
|
|
|
texel[ACOMP] = UBYTE_TO_FLOAT(texel_bytes[3]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int32_t
|
|
|
|
|
sign_extend(int32_t value,
|
|
|
|
|
int n_bits)
|
|
|
|
|
{
|
|
|
|
|
if ((value & (1 << (n_bits - 1)))) {
|
|
|
|
|
value |= (~(int32_t) 0) << n_bits;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
signed_unquantize(int value, int n_endpoint_bits)
|
|
|
|
|
{
|
|
|
|
|
bool sign;
|
|
|
|
|
|
|
|
|
|
if (n_endpoint_bits >= 16)
|
|
|
|
|
return value;
|
|
|
|
|
|
|
|
|
|
if (value == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
sign = false;
|
|
|
|
|
|
|
|
|
|
if (value < 0) {
|
|
|
|
|
sign = true;
|
|
|
|
|
value = -value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (value >= (1 << (n_endpoint_bits - 1)) - 1)
|
|
|
|
|
value = 0x7fff;
|
|
|
|
|
else
|
|
|
|
|
value = ((value << 15) + 0x4000) >> (n_endpoint_bits - 1);
|
|
|
|
|
|
|
|
|
|
if (sign)
|
|
|
|
|
value = -value;
|
|
|
|
|
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
unsigned_unquantize(int value, int n_endpoint_bits)
|
|
|
|
|
{
|
|
|
|
|
if (n_endpoint_bits >= 15)
|
|
|
|
|
return value;
|
|
|
|
|
|
|
|
|
|
if (value == 0)
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
|
|
if (value == (1 << n_endpoint_bits) - 1)
|
|
|
|
|
return 0xffff;
|
|
|
|
|
|
|
|
|
|
return ((value << 15) + 0x4000) >> (n_endpoint_bits - 1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
extract_float_endpoints(const struct bptc_float_mode *mode,
|
|
|
|
|
const uint8_t *block,
|
|
|
|
|
int bit_offset,
|
|
|
|
|
int32_t endpoints[][3],
|
|
|
|
|
bool is_signed)
|
|
|
|
|
{
|
|
|
|
|
const struct bptc_float_bitfield *bitfield;
|
|
|
|
|
int endpoint, component;
|
|
|
|
|
int n_endpoints;
|
|
|
|
|
int value;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (mode->n_partition_bits)
|
|
|
|
|
n_endpoints = 4;
|
|
|
|
|
else
|
|
|
|
|
n_endpoints = 2;
|
|
|
|
|
|
|
|
|
|
memset(endpoints, 0, sizeof endpoints[0][0] * n_endpoints * 3);
|
|
|
|
|
|
|
|
|
|
for (bitfield = mode->bitfields; bitfield->endpoint != -1; bitfield++) {
|
|
|
|
|
value = extract_bits(block, bit_offset, bitfield->n_bits);
|
|
|
|
|
bit_offset += bitfield->n_bits;
|
|
|
|
|
|
|
|
|
|
if (bitfield->reverse) {
|
|
|
|
|
for (i = 0; i < bitfield->n_bits; i++) {
|
|
|
|
|
if (value & (1 << i))
|
|
|
|
|
endpoints[bitfield->endpoint][bitfield->component] |=
|
|
|
|
|
1 << ((bitfield->n_bits - 1 - i) + bitfield->offset);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
endpoints[bitfield->endpoint][bitfield->component] |=
|
|
|
|
|
value << bitfield->offset;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mode->transformed_endpoints) {
|
|
|
|
|
/* The endpoints are specified as signed offsets from e0 */
|
|
|
|
|
for (endpoint = 1; endpoint < n_endpoints; endpoint++) {
|
|
|
|
|
for (component = 0; component < 3; component++) {
|
|
|
|
|
value = sign_extend(endpoints[endpoint][component],
|
|
|
|
|
mode->n_delta_bits[component]);
|
|
|
|
|
endpoints[endpoint][component] =
|
|
|
|
|
((endpoints[0][component] + value) &
|
|
|
|
|
((1 << mode->n_endpoint_bits) - 1));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (is_signed) {
|
|
|
|
|
for (endpoint = 0; endpoint < n_endpoints; endpoint++) {
|
|
|
|
|
for (component = 0; component < 3; component++) {
|
|
|
|
|
value = sign_extend(endpoints[endpoint][component],
|
|
|
|
|
mode->n_endpoint_bits);
|
|
|
|
|
endpoints[endpoint][component] =
|
|
|
|
|
signed_unquantize(value, mode->n_endpoint_bits);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
for (endpoint = 0; endpoint < n_endpoints; endpoint++) {
|
|
|
|
|
for (component = 0; component < 3; component++) {
|
|
|
|
|
endpoints[endpoint][component] =
|
|
|
|
|
unsigned_unquantize(endpoints[endpoint][component],
|
|
|
|
|
mode->n_endpoint_bits);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bit_offset;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int32_t
|
|
|
|
|
finish_unsigned_unquantize(int32_t value)
|
|
|
|
|
{
|
|
|
|
|
return value * 31 / 64;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int32_t
|
|
|
|
|
finish_signed_unquantize(int32_t value)
|
|
|
|
|
{
|
|
|
|
|
if (value < 0)
|
|
|
|
|
return (-value * 31 / 32) | 0x8000;
|
|
|
|
|
else
|
|
|
|
|
return value * 31 / 32;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_rgb_float_from_block(const uint8_t *block,
|
|
|
|
|
float *result,
|
|
|
|
|
int texel,
|
|
|
|
|
bool is_signed)
|
|
|
|
|
{
|
|
|
|
|
int mode_num;
|
|
|
|
|
const struct bptc_float_mode *mode;
|
|
|
|
|
int bit_offset;
|
|
|
|
|
int partition_num;
|
|
|
|
|
int subset_num;
|
|
|
|
|
int index_bits;
|
|
|
|
|
int index;
|
|
|
|
|
int anchors_before_texel;
|
|
|
|
|
int32_t endpoints[2 * 2][3];
|
|
|
|
|
uint32_t subsets;
|
|
|
|
|
int n_subsets;
|
|
|
|
|
int component;
|
|
|
|
|
int32_t value;
|
|
|
|
|
|
|
|
|
|
if (block[0] & 0x2) {
|
|
|
|
|
mode_num = (((block[0] >> 1) & 0xe) | (block[0] & 1)) + 2;
|
|
|
|
|
bit_offset = 5;
|
|
|
|
|
} else {
|
|
|
|
|
mode_num = block[0] & 3;
|
|
|
|
|
bit_offset = 2;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mode = bptc_float_modes + mode_num;
|
|
|
|
|
|
|
|
|
|
if (mode->reserved) {
|
|
|
|
|
memset(result, 0, sizeof result[0] * 3);
|
|
|
|
|
result[3] = 1.0f;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bit_offset = extract_float_endpoints(mode, block, bit_offset,
|
|
|
|
|
endpoints, is_signed);
|
|
|
|
|
|
|
|
|
|
if (mode->n_partition_bits) {
|
|
|
|
|
partition_num = extract_bits(block, bit_offset, mode->n_partition_bits);
|
|
|
|
|
bit_offset += mode->n_partition_bits;
|
|
|
|
|
|
|
|
|
|
subsets = partition_table1[partition_num];
|
|
|
|
|
n_subsets = 2;
|
|
|
|
|
} else {
|
|
|
|
|
partition_num = 0;
|
|
|
|
|
subsets = 0;
|
|
|
|
|
n_subsets = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
anchors_before_texel =
|
|
|
|
|
count_anchors_before_texel(n_subsets, partition_num, texel);
|
|
|
|
|
|
|
|
|
|
/* Calculate the offset to the primary index for this texel */
|
|
|
|
|
bit_offset += mode->n_index_bits * texel - anchors_before_texel;
|
|
|
|
|
|
|
|
|
|
subset_num = (subsets >> (texel * 2)) & 3;
|
|
|
|
|
|
|
|
|
|
index_bits = mode->n_index_bits;
|
|
|
|
|
if (is_anchor(n_subsets, partition_num, texel))
|
|
|
|
|
index_bits--;
|
|
|
|
|
index = extract_bits(block, bit_offset, index_bits);
|
|
|
|
|
|
|
|
|
|
for (component = 0; component < 3; component++) {
|
|
|
|
|
value = interpolate(endpoints[subset_num * 2][component],
|
|
|
|
|
endpoints[subset_num * 2 + 1][component],
|
|
|
|
|
index,
|
|
|
|
|
mode->n_index_bits);
|
|
|
|
|
|
|
|
|
|
if (is_signed)
|
|
|
|
|
value = finish_signed_unquantize(value);
|
|
|
|
|
else
|
|
|
|
|
value = finish_unsigned_unquantize(value);
|
|
|
|
|
|
|
|
|
|
result[component] = _mesa_half_to_float(value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
result[3] = 1.0f;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_bptc_rgb_float(const GLubyte *map,
|
|
|
|
|
GLint rowStride, GLint i, GLint j,
|
|
|
|
|
GLfloat *texel,
|
|
|
|
|
bool is_signed)
|
|
|
|
|
{
|
|
|
|
|
const GLubyte *block;
|
|
|
|
|
|
|
|
|
|
block = map + (((rowStride + 3) / 4) * (j / 4) + (i / 4)) * 16;
|
|
|
|
|
|
|
|
|
|
fetch_rgb_float_from_block(block, texel, (i % 4) + (j % 4) * 4, is_signed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_bptc_rgb_signed_float(const GLubyte *map,
|
|
|
|
|
GLint rowStride, GLint i, GLint j,
|
|
|
|
|
GLfloat *texel)
|
|
|
|
|
{
|
|
|
|
|
fetch_bptc_rgb_float(map, rowStride, i, j, texel, true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
fetch_bptc_rgb_unsigned_float(const GLubyte *map,
|
|
|
|
|
GLint rowStride, GLint i, GLint j,
|
|
|
|
|
GLfloat *texel)
|
|
|
|
|
{
|
|
|
|
|
fetch_bptc_rgb_float(map, rowStride, i, j, texel, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
compressed_fetch_func
|
|
|
|
|
_mesa_get_bptc_fetch_func(mesa_format format)
|
|
|
|
|
{
|
|
|
|
|
switch (format) {
|
|
|
|
|
case MESA_FORMAT_BPTC_RGBA_UNORM:
|
|
|
|
|
return fetch_bptc_rgba_unorm;
|
|
|
|
|
case MESA_FORMAT_BPTC_SRGB_ALPHA_UNORM:
|
|
|
|
|
return fetch_bptc_srgb_alpha_unorm;
|
|
|
|
|
case MESA_FORMAT_BPTC_RGB_SIGNED_FLOAT:
|
|
|
|
|
return fetch_bptc_rgb_signed_float;
|
|
|
|
|
case MESA_FORMAT_BPTC_RGB_UNSIGNED_FLOAT:
|
|
|
|
|
return fetch_bptc_rgb_unsigned_float;
|
|
|
|
|
default:
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|