1 | // File: basisu_bc7enc.h |
2 | // Copyright (C) 2019-2021 Binomial LLC. All Rights Reserved. |
3 | // |
4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | // you may not use this file except in compliance with the License. |
6 | // You may obtain a copy of the License at |
7 | // |
8 | // http://www.apache.org/licenses/LICENSE-2.0 |
9 | // |
10 | // Unless required by applicable law or agreed to in writing, software |
11 | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | // See the License for the specific language governing permissions and |
14 | // limitations under the License. |
15 | #pragma once |
16 | #include "basisu_enc.h" |
17 | #include "../transcoder/basisu_transcoder_uastc.h" |
18 | |
19 | namespace basisu |
20 | { |
21 | |
22 | #define BC7ENC_MAX_PARTITIONS1 (64) |
23 | #define BC7ENC_MAX_UBER_LEVEL (4) |
24 | |
25 | typedef uint8_t bc7enc_bool; |
26 | |
27 | #define BC7ENC_TRUE (1) |
28 | #define BC7ENC_FALSE (0) |
29 | |
30 | typedef struct { float m_c[4]; } bc7enc_vec4F; |
31 | |
32 | extern const float g_bc7_weights1x[2 * 4]; |
33 | extern const float g_bc7_weights2x[4 * 4]; |
34 | extern const float g_bc7_weights3x[8 * 4]; |
35 | extern const float g_bc7_weights4x[16 * 4]; |
36 | extern const float g_astc_weights4x[16 * 4]; |
37 | extern const float g_astc_weights5x[32 * 4]; |
38 | extern const float g_astc_weights_3levelsx[3 * 4]; |
39 | |
40 | extern basist::astc_quant_bin g_astc_sorted_order_unquant[basist::BC7ENC_TOTAL_ASTC_RANGES][256]; // [sorted unquantized order] |
41 | |
42 | struct color_cell_compressor_params |
43 | { |
44 | uint32_t m_num_pixels; |
45 | const basist::color_quad_u8* m_pPixels; |
46 | |
47 | uint32_t m_num_selector_weights; |
48 | const uint32_t* m_pSelector_weights; |
49 | |
50 | const bc7enc_vec4F* m_pSelector_weightsx; |
51 | uint32_t m_comp_bits; |
52 | |
53 | const uint8_t *m_pForce_selectors; |
54 | |
55 | // Non-zero m_astc_endpoint_range enables ASTC mode. m_comp_bits and m_has_pbits are always false. We only support 2, 3, or 4 bit weight encodings. |
56 | uint32_t m_astc_endpoint_range; |
57 | |
58 | uint32_t m_weights[4]; |
59 | bc7enc_bool m_has_alpha; |
60 | bc7enc_bool m_has_pbits; |
61 | bc7enc_bool m_endpoints_share_pbit; |
62 | bc7enc_bool m_perceptual; |
63 | }; |
64 | |
65 | struct color_cell_compressor_results |
66 | { |
67 | uint64_t m_best_overall_err; |
68 | basist::color_quad_u8 m_low_endpoint; |
69 | basist::color_quad_u8 m_high_endpoint; |
70 | uint32_t m_pbits[2]; |
71 | uint8_t* m_pSelectors; |
72 | uint8_t* m_pSelectors_temp; |
73 | |
74 | // Encoded ASTC indices, if ASTC mode is enabled |
75 | basist::color_quad_u8 m_astc_low_endpoint; |
76 | basist::color_quad_u8 m_astc_high_endpoint; |
77 | }; |
78 | |
79 | struct bc7enc_compress_block_params |
80 | { |
81 | // m_max_partitions_mode1 may range from 0 (disables mode 1) to BC7ENC_MAX_PARTITIONS1. The higher this value, the slower the compressor, but the higher the quality. |
82 | uint32_t m_max_partitions_mode1; |
83 | |
84 | // Relative RGBA or YCbCrA weights. |
85 | uint32_t m_weights[4]; |
86 | |
87 | // m_uber_level may range from 0 to BC7ENC_MAX_UBER_LEVEL. The higher this value, the slower the compressor, but the higher the quality. |
88 | uint32_t m_uber_level; |
89 | |
90 | // If m_perceptual is true, colorspace error is computed in YCbCr space, otherwise RGB. |
91 | bc7enc_bool m_perceptual; |
92 | |
93 | uint32_t m_least_squares_passes; |
94 | }; |
95 | |
96 | uint64_t color_cell_compression(uint32_t mode, const color_cell_compressor_params* pParams, color_cell_compressor_results* pResults, const bc7enc_compress_block_params* pComp_params); |
97 | |
98 | uint64_t color_cell_compression_est_astc( |
99 | uint32_t num_weights, uint32_t num_comps, const uint32_t* pWeight_table, |
100 | uint32_t num_pixels, const basist::color_quad_u8* pPixels, |
101 | uint64_t best_err_so_far, const uint32_t weights[4]); |
102 | |
103 | inline void bc7enc_compress_block_params_init_linear_weights(bc7enc_compress_block_params* p) |
104 | { |
105 | p->m_perceptual = BC7ENC_FALSE; |
106 | p->m_weights[0] = 1; |
107 | p->m_weights[1] = 1; |
108 | p->m_weights[2] = 1; |
109 | p->m_weights[3] = 1; |
110 | } |
111 | |
112 | inline void bc7enc_compress_block_params_init_perceptual_weights(bc7enc_compress_block_params* p) |
113 | { |
114 | p->m_perceptual = BC7ENC_TRUE; |
115 | p->m_weights[0] = 128; |
116 | p->m_weights[1] = 64; |
117 | p->m_weights[2] = 16; |
118 | p->m_weights[3] = 32; |
119 | } |
120 | |
121 | inline void bc7enc_compress_block_params_init(bc7enc_compress_block_params* p) |
122 | { |
123 | p->m_max_partitions_mode1 = BC7ENC_MAX_PARTITIONS1; |
124 | p->m_least_squares_passes = 1; |
125 | p->m_uber_level = 0; |
126 | bc7enc_compress_block_params_init_perceptual_weights(p); |
127 | } |
128 | |
129 | // bc7enc_compress_block_init() MUST be called before calling bc7enc_compress_block() (or you'll get artifacts). |
130 | void bc7enc_compress_block_init(); |
131 | |
132 | } // namespace basisu |
133 | |