| 1 | // basisu_transcoder_uastc.h | 
|---|
| 2 | #pragma once | 
|---|
| 3 | #include "basisu_transcoder_internal.h" | 
|---|
| 4 |  | 
|---|
| 5 | namespace basist | 
|---|
| 6 | { | 
|---|
| 7 | struct color_quad_u8 | 
|---|
| 8 | { | 
|---|
| 9 | uint8_t m_c[4]; | 
|---|
| 10 | }; | 
|---|
| 11 |  | 
|---|
| 12 | const uint32_t TOTAL_UASTC_MODES = 19; | 
|---|
| 13 | const uint32_t UASTC_MODE_INDEX_SOLID_COLOR = 8; | 
|---|
| 14 |  | 
|---|
| 15 | const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS2 = 30; | 
|---|
| 16 | const uint32_t TOTAL_ASTC_BC7_COMMON_PARTITIONS3 = 11; | 
|---|
| 17 | const uint32_t TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS = 19; | 
|---|
| 18 |  | 
|---|
| 19 | extern const uint8_t g_uastc_mode_weight_bits[TOTAL_UASTC_MODES]; | 
|---|
| 20 | extern const uint8_t g_uastc_mode_weight_ranges[TOTAL_UASTC_MODES]; | 
|---|
| 21 | extern const uint8_t g_uastc_mode_endpoint_ranges[TOTAL_UASTC_MODES]; | 
|---|
| 22 | extern const uint8_t g_uastc_mode_subsets[TOTAL_UASTC_MODES]; | 
|---|
| 23 | extern const uint8_t g_uastc_mode_planes[TOTAL_UASTC_MODES]; | 
|---|
| 24 | extern const uint8_t g_uastc_mode_comps[TOTAL_UASTC_MODES]; | 
|---|
| 25 | extern const uint8_t g_uastc_mode_has_etc1_bias[TOTAL_UASTC_MODES]; | 
|---|
| 26 | extern const uint8_t g_uastc_mode_has_bc1_hint0[TOTAL_UASTC_MODES]; | 
|---|
| 27 | extern const uint8_t g_uastc_mode_has_bc1_hint1[TOTAL_UASTC_MODES]; | 
|---|
| 28 | extern const uint8_t g_uastc_mode_has_alpha[TOTAL_UASTC_MODES]; | 
|---|
| 29 | extern const uint8_t g_uastc_mode_is_la[TOTAL_UASTC_MODES]; | 
|---|
| 30 |  | 
|---|
| 31 | struct astc_bc7_common_partition2_desc | 
|---|
| 32 | { | 
|---|
| 33 | uint8_t m_bc7; | 
|---|
| 34 | uint16_t m_astc; | 
|---|
| 35 | bool m_invert; | 
|---|
| 36 | }; | 
|---|
| 37 |  | 
|---|
| 38 | extern const astc_bc7_common_partition2_desc g_astc_bc7_common_partitions2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2]; | 
|---|
| 39 |  | 
|---|
| 40 | struct bc73_astc2_common_partition_desc | 
|---|
| 41 | { | 
|---|
| 42 | uint8_t m_bc73; | 
|---|
| 43 | uint16_t m_astc2; | 
|---|
| 44 | uint8_t k;		// 0-5 - how to modify the BC7 3-subset pattern to match the ASTC pattern (LSB=invert) | 
|---|
| 45 | }; | 
|---|
| 46 |  | 
|---|
| 47 | extern const bc73_astc2_common_partition_desc g_bc7_3_astc2_common_partitions[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS]; | 
|---|
| 48 |  | 
|---|
| 49 | struct astc_bc7_common_partition3_desc | 
|---|
| 50 | { | 
|---|
| 51 | uint8_t m_bc7; | 
|---|
| 52 | uint16_t m_astc; | 
|---|
| 53 | uint8_t m_astc_to_bc7_perm; // converts ASTC to BC7 partition using g_astc_bc7_partition_index_perm_tables[][] | 
|---|
| 54 | }; | 
|---|
| 55 |  | 
|---|
| 56 | extern const astc_bc7_common_partition3_desc g_astc_bc7_common_partitions3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3]; | 
|---|
| 57 |  | 
|---|
| 58 | extern const uint8_t g_astc_bc7_patterns2[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][16]; | 
|---|
| 59 | extern const uint8_t g_astc_bc7_patterns3[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][16]; | 
|---|
| 60 | extern const uint8_t g_bc7_3_astc2_patterns2[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][16]; | 
|---|
| 61 |  | 
|---|
| 62 | extern const uint8_t g_astc_bc7_pattern2_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS2][3]; | 
|---|
| 63 | extern const uint8_t g_astc_bc7_pattern3_anchors[TOTAL_ASTC_BC7_COMMON_PARTITIONS3][3]; | 
|---|
| 64 | extern const uint8_t g_bc7_3_astc2_patterns2_anchors[TOTAL_BC7_3_ASTC2_COMMON_PARTITIONS][3]; | 
|---|
| 65 |  | 
|---|
| 66 | extern const uint32_t g_uastc_mode_huff_codes[TOTAL_UASTC_MODES + 1][2]; | 
|---|
| 67 |  | 
|---|
| 68 | extern const uint8_t g_astc_to_bc7_partition_index_perm_tables[6][3]; | 
|---|
| 69 | extern const uint8_t g_bc7_to_astc_partition_index_perm_tables[6][3]; // inverse of g_astc_to_bc7_partition_index_perm_tables | 
|---|
| 70 |  | 
|---|
| 71 | extern const uint8_t* s_uastc_to_bc1_weights[6]; | 
|---|
| 72 |  | 
|---|
| 73 | uint32_t bc7_convert_partition_index_3_to_2(uint32_t p, uint32_t k); | 
|---|
| 74 |  | 
|---|
| 75 | inline uint32_t astc_interpolate(uint32_t l, uint32_t h, uint32_t w, bool srgb) | 
|---|
| 76 | { | 
|---|
| 77 | if (srgb) | 
|---|
| 78 | { | 
|---|
| 79 | l = (l << 8) | 0x80; | 
|---|
| 80 | h = (h << 8) | 0x80; | 
|---|
| 81 | } | 
|---|
| 82 | else | 
|---|
| 83 | { | 
|---|
| 84 | l = (l << 8) | l; | 
|---|
| 85 | h = (h << 8) | h; | 
|---|
| 86 | } | 
|---|
| 87 |  | 
|---|
| 88 | uint32_t k = (l * (64 - w) + h * w + 32) >> 6; | 
|---|
| 89 |  | 
|---|
| 90 | return k >> 8; | 
|---|
| 91 | } | 
|---|
| 92 |  | 
|---|
| 93 | struct astc_block_desc | 
|---|
| 94 | { | 
|---|
| 95 | int m_weight_range;	// weight BISE range | 
|---|
| 96 |  | 
|---|
| 97 | int m_subsets;			// number of ASTC partitions | 
|---|
| 98 | int m_partition_seed;	// partition pattern seed | 
|---|
| 99 | int m_cem;				// color endpoint mode used by all subsets | 
|---|
| 100 |  | 
|---|
| 101 | int m_ccs;				// color component selector (dual plane only) | 
|---|
| 102 | bool m_dual_plane;	// true if dual plane | 
|---|
| 103 |  | 
|---|
| 104 | // Weight and endpoint BISE values. | 
|---|
| 105 | // Note these values are NOT linear, they must be BISE encoded. See Table 97 and Table 107. | 
|---|
| 106 | uint8_t m_endpoints[18];	// endpoint values, in RR GG BB etc. order | 
|---|
| 107 | uint8_t m_weights[64];		// weight index values, raster order, in P0 P1, P0 P1, etc. or P0, P0, P0, P0, etc. order | 
|---|
| 108 | }; | 
|---|
| 109 |  | 
|---|
| 110 | const uint32_t BC7ENC_TOTAL_ASTC_RANGES = 21; | 
|---|
| 111 |  | 
|---|
| 112 | // See tables 81, 93, 18.13.Endpoint Unquantization | 
|---|
| 113 | const uint32_t TOTAL_ASTC_RANGES = 21; | 
|---|
| 114 | extern const int g_astc_bise_range_table[TOTAL_ASTC_RANGES][3]; | 
|---|
| 115 |  | 
|---|
| 116 | struct astc_quant_bin | 
|---|
| 117 | { | 
|---|
| 118 | uint8_t m_unquant; // unquantized value | 
|---|
| 119 | uint8_t m_index; // sorted index | 
|---|
| 120 | }; | 
|---|
| 121 |  | 
|---|
| 122 | extern astc_quant_bin g_astc_unquant[BC7ENC_TOTAL_ASTC_RANGES][256]; // [ASTC encoded endpoint index] | 
|---|
| 123 |  | 
|---|
| 124 | int astc_get_levels(int range); | 
|---|
| 125 | bool astc_is_valid_endpoint_range(uint32_t range); | 
|---|
| 126 | uint32_t unquant_astc_endpoint(uint32_t packed_bits, uint32_t packed_trits, uint32_t packed_quints, uint32_t range); | 
|---|
| 127 | uint32_t unquant_astc_endpoint_val(uint32_t packed_val, uint32_t range); | 
|---|
| 128 |  | 
|---|
| 129 | const uint8_t* get_anchor_indices(uint32_t subsets, uint32_t mode, uint32_t common_pattern, const uint8_t*& pPartition_pattern); | 
|---|
| 130 |  | 
|---|
| 131 | // BC7 | 
|---|
| 132 | const uint32_t BC7ENC_BLOCK_SIZE = 16; | 
|---|
| 133 |  | 
|---|
| 134 | struct bc7_block | 
|---|
| 135 | { | 
|---|
| 136 | uint64_t m_qwords[2]; | 
|---|
| 137 | }; | 
|---|
| 138 |  | 
|---|
| 139 | struct bc7_optimization_results | 
|---|
| 140 | { | 
|---|
| 141 | uint32_t m_mode; | 
|---|
| 142 | uint32_t m_partition; | 
|---|
| 143 | uint8_t m_selectors[16]; | 
|---|
| 144 | uint8_t m_alpha_selectors[16]; | 
|---|
| 145 | color_quad_u8 m_low[3]; | 
|---|
| 146 | color_quad_u8 m_high[3]; | 
|---|
| 147 | uint32_t m_pbits[3][2]; | 
|---|
| 148 | uint32_t m_index_selector; | 
|---|
| 149 | uint32_t m_rotation; | 
|---|
| 150 | }; | 
|---|
| 151 |  | 
|---|
| 152 | extern const uint32_t g_bc7_weights1[2]; | 
|---|
| 153 | extern const uint32_t g_bc7_weights2[4]; | 
|---|
| 154 | extern const uint32_t g_bc7_weights3[8]; | 
|---|
| 155 | extern const uint32_t g_bc7_weights4[16]; | 
|---|
| 156 | extern const uint32_t g_astc_weights4[16]; | 
|---|
| 157 | extern const uint32_t g_astc_weights5[32]; | 
|---|
| 158 | extern const uint32_t g_astc_weights_3levels[3]; | 
|---|
| 159 | extern const uint8_t g_bc7_partition1[16]; | 
|---|
| 160 | extern const uint8_t g_bc7_partition2[64 * 16]; | 
|---|
| 161 | extern const uint8_t g_bc7_partition3[64 * 16]; | 
|---|
| 162 | extern const uint8_t g_bc7_table_anchor_index_second_subset[64]; | 
|---|
| 163 | extern const uint8_t g_bc7_table_anchor_index_third_subset_1[64]; | 
|---|
| 164 | extern const uint8_t g_bc7_table_anchor_index_third_subset_2[64]; | 
|---|
| 165 | extern const uint8_t g_bc7_num_subsets[8]; | 
|---|
| 166 | extern const uint8_t g_bc7_partition_bits[8]; | 
|---|
| 167 | extern const uint8_t g_bc7_color_index_bitcount[8]; | 
|---|
| 168 | extern const uint8_t g_bc7_mode_has_p_bits[8]; | 
|---|
| 169 | extern const uint8_t g_bc7_mode_has_shared_p_bits[8]; | 
|---|
| 170 | extern const uint8_t g_bc7_color_precision_table[8]; | 
|---|
| 171 | extern const int8_t g_bc7_alpha_precision_table[8]; | 
|---|
| 172 | extern const uint8_t g_bc7_alpha_index_bitcount[8]; | 
|---|
| 173 |  | 
|---|
| 174 | inline bool get_bc7_mode_has_seperate_alpha_selectors(int mode) { return (mode == 4) || (mode == 5); } | 
|---|
| 175 | inline int get_bc7_color_index_size(int mode, int index_selection_bit) { return g_bc7_color_index_bitcount[mode] + index_selection_bit; } | 
|---|
| 176 | inline int get_bc7_alpha_index_size(int mode, int index_selection_bit) { return g_bc7_alpha_index_bitcount[mode] - index_selection_bit; } | 
|---|
| 177 |  | 
|---|
| 178 | struct endpoint_err | 
|---|
| 179 | { | 
|---|
| 180 | uint16_t m_error; uint8_t m_lo; uint8_t m_hi; | 
|---|
| 181 | }; | 
|---|
| 182 |  | 
|---|
| 183 | extern endpoint_err g_bc7_mode_6_optimal_endpoints[256][2]; // [c][pbit] | 
|---|
| 184 | const uint32_t BC7ENC_MODE_6_OPTIMAL_INDEX = 5; | 
|---|
| 185 |  | 
|---|
| 186 | extern endpoint_err g_bc7_mode_5_optimal_endpoints[256]; // [c] | 
|---|
| 187 | const uint32_t BC7ENC_MODE_5_OPTIMAL_INDEX = 1; | 
|---|
| 188 |  | 
|---|
| 189 | // Packs a BC7 block from a high-level description. Handles all BC7 modes. | 
|---|
| 190 | void encode_bc7_block(void* pBlock, const bc7_optimization_results* pResults); | 
|---|
| 191 |  | 
|---|
| 192 | // Packs an ASTC block | 
|---|
| 193 | // Constraints: Always 4x4, all subset CEM's must be equal, only tested with LDR CEM's. | 
|---|
| 194 | bool pack_astc_block(uint32_t* pDst, const astc_block_desc* pBlock, uint32_t mode); | 
|---|
| 195 |  | 
|---|
| 196 | void pack_astc_solid_block(void* pDst_block, const color32& color); | 
|---|
| 197 |  | 
|---|
| 198 | #ifdef _DEBUG | 
|---|
| 199 | int astc_compute_texel_partition(int seed, int x, int y, int z, int partitioncount, bool small_block); | 
|---|
| 200 | #endif | 
|---|
| 201 |  | 
|---|
| 202 | struct uastc_block | 
|---|
| 203 | { | 
|---|
| 204 | union | 
|---|
| 205 | { | 
|---|
| 206 | uint8_t m_bytes[16]; | 
|---|
| 207 | uint32_t m_dwords[4]; | 
|---|
| 208 | }; | 
|---|
| 209 | }; | 
|---|
| 210 |  | 
|---|
| 211 | struct unpacked_uastc_block | 
|---|
| 212 | { | 
|---|
| 213 | astc_block_desc m_astc; | 
|---|
| 214 |  | 
|---|
| 215 | uint32_t m_mode; | 
|---|
| 216 | uint32_t m_common_pattern; | 
|---|
| 217 |  | 
|---|
| 218 | color32 m_solid_color; | 
|---|
| 219 |  | 
|---|
| 220 | bool m_bc1_hint0; | 
|---|
| 221 | bool m_bc1_hint1; | 
|---|
| 222 |  | 
|---|
| 223 | bool m_etc1_flip; | 
|---|
| 224 | bool m_etc1_diff; | 
|---|
| 225 | uint32_t m_etc1_inten0; | 
|---|
| 226 | uint32_t m_etc1_inten1; | 
|---|
| 227 |  | 
|---|
| 228 | uint32_t m_etc1_bias; | 
|---|
| 229 |  | 
|---|
| 230 | uint32_t m_etc2_hints; | 
|---|
| 231 |  | 
|---|
| 232 | uint32_t m_etc1_selector; | 
|---|
| 233 | uint32_t m_etc1_r, m_etc1_g, m_etc1_b; | 
|---|
| 234 | }; | 
|---|
| 235 |  | 
|---|
| 236 | color32 apply_etc1_bias(const color32 &block_color, uint32_t bias, uint32_t limit, uint32_t subblock); | 
|---|
| 237 |  | 
|---|
| 238 | struct decoder_etc_block; | 
|---|
| 239 | struct eac_block; | 
|---|
| 240 |  | 
|---|
| 241 | bool unpack_uastc(uint32_t mode, uint32_t common_pattern, const color32& solid_color, const astc_block_desc& astc, color32* pPixels, bool srgb); | 
|---|
| 242 | bool unpack_uastc(const unpacked_uastc_block& unpacked_blk, color32* pPixels, bool srgb); | 
|---|
| 243 |  | 
|---|
| 244 | bool unpack_uastc(const uastc_block& blk, color32* pPixels, bool srgb); | 
|---|
| 245 | bool unpack_uastc(const uastc_block& blk, unpacked_uastc_block& unpacked, bool undo_blue_contract, bool read_hints = true); | 
|---|
| 246 |  | 
|---|
| 247 | bool transcode_uastc_to_astc(const uastc_block& src_blk, void* pDst); | 
|---|
| 248 |  | 
|---|
| 249 | bool transcode_uastc_to_bc7(const unpacked_uastc_block& unpacked_src_blk, bc7_optimization_results& dst_blk); | 
|---|
| 250 | bool transcode_uastc_to_bc7(const uastc_block& src_blk, bc7_optimization_results& dst_blk); | 
|---|
| 251 | bool transcode_uastc_to_bc7(const uastc_block& src_blk, void* pDst); | 
|---|
| 252 |  | 
|---|
| 253 | void transcode_uastc_to_etc1(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst); | 
|---|
| 254 | bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst); | 
|---|
| 255 | bool transcode_uastc_to_etc1(const uastc_block& src_blk, void* pDst, uint32_t channel); | 
|---|
| 256 |  | 
|---|
| 257 | void transcode_uastc_to_etc2_eac_a8(unpacked_uastc_block& unpacked_src_blk, color32 block_pixels[4][4], void* pDst); | 
|---|
| 258 | bool transcode_uastc_to_etc2_rgba(const uastc_block& src_blk, void* pDst); | 
|---|
| 259 |  | 
|---|
| 260 | // Packs 16 scalar values to BC4. Same PSNR as stb_dxt's BC4 encoder, around 13% faster. | 
|---|
| 261 | void encode_bc4(void* pDst, const uint8_t* pPixels, uint32_t stride); | 
|---|
| 262 |  | 
|---|
| 263 | void encode_bc1_solid_block(void* pDst, uint32_t fr, uint32_t fg, uint32_t fb); | 
|---|
| 264 |  | 
|---|
| 265 | enum | 
|---|
| 266 | { | 
|---|
| 267 | cEncodeBC1HighQuality = 1, | 
|---|
| 268 | cEncodeBC1HigherQuality = 2, | 
|---|
| 269 | cEncodeBC1UseSelectors = 4, | 
|---|
| 270 | }; | 
|---|
| 271 | void encode_bc1(void* pDst, const uint8_t* pPixels, uint32_t flags); | 
|---|
| 272 |  | 
|---|
| 273 | // Alternate PCA-free encoder, around 15% faster, same (or slightly higher) avg. PSNR | 
|---|
| 274 | void encode_bc1_alt(void* pDst, const uint8_t* pPixels, uint32_t flags); | 
|---|
| 275 |  | 
|---|
| 276 | void transcode_uastc_to_bc1_hint0(const unpacked_uastc_block& unpacked_src_blk, void* pDst); | 
|---|
| 277 | void transcode_uastc_to_bc1_hint1(const unpacked_uastc_block& unpacked_src_blk, const color32 block_pixels[4][4], void* pDst, bool high_quality); | 
|---|
| 278 |  | 
|---|
| 279 | bool transcode_uastc_to_bc1(const uastc_block& src_blk, void* pDst, bool high_quality); | 
|---|
| 280 | bool transcode_uastc_to_bc3(const uastc_block& src_blk, void* pDst, bool high_quality); | 
|---|
| 281 | bool transcode_uastc_to_bc4(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0); | 
|---|
| 282 | bool transcode_uastc_to_bc5(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1); | 
|---|
| 283 |  | 
|---|
| 284 | bool transcode_uastc_to_etc2_eac_r11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0); | 
|---|
| 285 | bool transcode_uastc_to_etc2_eac_rg11(const uastc_block& src_blk, void* pDst, bool high_quality, uint32_t chan0, uint32_t chan1); | 
|---|
| 286 |  | 
|---|
| 287 | bool transcode_uastc_to_pvrtc1_4_rgb(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality, bool from_alpha); | 
|---|
| 288 | bool transcode_uastc_to_pvrtc1_4_rgba(const uastc_block* pSrc_blocks, void* pDst_blocks, uint32_t num_blocks_x, uint32_t num_blocks_y, bool high_quality); | 
|---|
| 289 |  | 
|---|
| 290 | // uastc_init() MUST be called before using this module. | 
|---|
| 291 | void uastc_init(); | 
|---|
| 292 |  | 
|---|
| 293 | } // namespace basist | 
|---|
| 294 |  | 
|---|