1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2011-2020 Arm Limited
4 //
5 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
6 // use this file except in compliance with the License. You may obtain a copy
7 // of the License at:
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 // License for the specific language governing permissions and limitations
15 // under the License.
16 // ----------------------------------------------------------------------------
17
18 /**
19 * @brief Functions to decompress a symbolic block.
20 */
21
22 #include "astc_codec_internals.h"
23
compute_value_of_texel_int(int texel_to_get,const decimation_table * it,const int * weights)24 static int compute_value_of_texel_int(
25 int texel_to_get,
26 const decimation_table* it,
27 const int* weights
28 ) {
29 int i;
30 int summed_value = 8;
31 int weights_to_evaluate = it->texel_num_weights[texel_to_get];
32 for (i = 0; i < weights_to_evaluate; i++)
33 {
34 summed_value += weights[it->texel_weights[texel_to_get][i]] * it->texel_weights_int[texel_to_get][i];
35 }
36 return summed_value >> 4;
37 }
38
lerp_color_int(astc_decode_mode decode_mode,uint4 color0,uint4 color1,int weight,int plane2_weight,int plane2_color_component)39 static uint4 lerp_color_int(
40 astc_decode_mode decode_mode,
41 uint4 color0,
42 uint4 color1,
43 int weight,
44 int plane2_weight,
45 int plane2_color_component // -1 in 1-plane mode
46 ) {
47 int4 ecolor0 = int4(color0.x, color0.y, color0.z, color0.w);
48 int4 ecolor1 = int4(color1.x, color1.y, color1.z, color1.w);
49
50 int4 eweight1 = int4(weight, weight, weight, weight);
51 switch (plane2_color_component)
52 {
53 case 0:
54 eweight1.x = plane2_weight;
55 break;
56 case 1:
57 eweight1.y = plane2_weight;
58 break;
59 case 2:
60 eweight1.z = plane2_weight;
61 break;
62 case 3:
63 eweight1.w = plane2_weight;
64 break;
65 default:
66 break;
67 }
68
69 int4 eweight0 = int4(64, 64, 64, 64) - eweight1;
70
71 if (decode_mode == DECODE_LDR_SRGB)
72 {
73 ecolor0 = int4(ecolor0.x >> 8, ecolor0.y >> 8, ecolor0.z >> 8, ecolor0.w >> 8);
74 ecolor1 = int4(ecolor1.x >> 8, ecolor1.y >> 8, ecolor1.z >> 8, ecolor1.w >> 8);
75 }
76 int4 color = (ecolor0 * eweight0) + (ecolor1 * eweight1) + int4(32, 32, 32, 32);
77 color = int4(color.x >> 6, color.y >> 6, color.z >> 6, color.w >> 6);
78
79 if (decode_mode == DECODE_LDR_SRGB)
80 color = color * 257;
81
82 return uint4(color.x, color.y, color.z, color.w);
83 }
84
decompress_symbolic_block(astc_decode_mode decode_mode,const block_size_descriptor * bsd,int xpos,int ypos,int zpos,const symbolic_compressed_block * scb,imageblock * blk)85 void decompress_symbolic_block(
86 astc_decode_mode decode_mode,
87 const block_size_descriptor* bsd,
88 int xpos,
89 int ypos,
90 int zpos,
91 const symbolic_compressed_block* scb,
92 imageblock* blk
93 ) {
94 blk->xpos = xpos;
95 blk->ypos = ypos;
96 blk->zpos = zpos;
97
98 int i;
99
100 // if we detected an error-block, blow up immediately.
101 if (scb->error_block)
102 {
103 if (decode_mode == DECODE_LDR_SRGB)
104 {
105 for (i = 0; i < bsd->texel_count; i++)
106 {
107 blk->orig_data[4 * i] = 1.0f;
108 blk->orig_data[4 * i + 1] = 0.0f;
109 blk->orig_data[4 * i + 2] = 1.0f;
110 blk->orig_data[4 * i + 3] = 1.0f;
111 blk->rgb_lns[i] = 0;
112 blk->alpha_lns[i] = 0;
113 blk->nan_texel[i] = 0;
114 }
115 }
116 else
117 {
118 for (i = 0; i < bsd->texel_count; i++)
119 {
120 blk->orig_data[4 * i] = 0.0f;
121 blk->orig_data[4 * i + 1] = 0.0f;
122 blk->orig_data[4 * i + 2] = 0.0f;
123 blk->orig_data[4 * i + 3] = 0.0f;
124 blk->rgb_lns[i] = 0;
125 blk->alpha_lns[i] = 0;
126 blk->nan_texel[i] = 1;
127 }
128 }
129
130 imageblock_initialize_work_from_orig(blk, bsd->texel_count);
131 update_imageblock_flags(blk, bsd->xdim, bsd->ydim, bsd->zdim);
132 return;
133 }
134
135 if (scb->block_mode < 0)
136 {
137 float red = 0, green = 0, blue = 0, alpha = 0;
138 int use_lns = 0;
139 int use_nan = 0;
140
141 if (scb->block_mode == -2)
142 {
143 // For sRGB decoding, we should return only the top 8 bits.
144 int mask = (decode_mode == DECODE_LDR_SRGB) ? 0xFF00 : 0xFFFF;
145
146 red = sf16_to_float(unorm16_to_sf16(scb->constant_color[0] & mask));
147 green = sf16_to_float(unorm16_to_sf16(scb->constant_color[1] & mask));
148 blue = sf16_to_float(unorm16_to_sf16(scb->constant_color[2] & mask));
149 alpha = sf16_to_float(unorm16_to_sf16(scb->constant_color[3] & mask));
150 use_lns = 0;
151 use_nan = 0;
152 }
153 else
154 {
155 switch (decode_mode)
156 {
157 case DECODE_LDR_SRGB:
158 red = 1.0f;
159 green = 0.0f;
160 blue = 1.0f;
161 alpha = 1.0f;
162 use_lns = 0;
163 use_nan = 0;
164 break;
165 case DECODE_LDR:
166 red = 0.0f;
167 green = 0.0f;
168 blue = 0.0f;
169 alpha = 0.0f;
170 use_lns = 0;
171 use_nan = 1;
172 break;
173 case DECODE_HDR:
174 // constant-color block; unpack from FP16 to FP32.
175 red = sf16_to_float(scb->constant_color[0]);
176 green = sf16_to_float(scb->constant_color[1]);
177 blue = sf16_to_float(scb->constant_color[2]);
178 alpha = sf16_to_float(scb->constant_color[3]);
179 use_lns = 1;
180 use_nan = 0;
181 break;
182 }
183 }
184
185 for (i = 0; i < bsd->texel_count; i++)
186 {
187 blk->orig_data[4 * i] = red;
188 blk->orig_data[4 * i + 1] = green;
189 blk->orig_data[4 * i + 2] = blue;
190 blk->orig_data[4 * i + 3] = alpha;
191 blk->rgb_lns[i] = use_lns;
192 blk->alpha_lns[i] = use_lns;
193 blk->nan_texel[i] = use_nan;
194 }
195
196 imageblock_initialize_work_from_orig(blk, bsd->texel_count);
197 update_imageblock_flags(blk, bsd->xdim, bsd->ydim, bsd->zdim);
198 return;
199 }
200
201 // get the appropriate partition-table entry
202 int partition_count = scb->partition_count;
203 const partition_info *pt = get_partition_table(bsd, partition_count);
204 pt += scb->partition_index;
205
206 // get the appropriate block descriptor
207 const decimation_table *const *ixtab2 = bsd->decimation_tables;
208
209 const decimation_table *it = ixtab2[bsd->block_modes[scb->block_mode].decimation_mode];
210
211 int is_dual_plane = bsd->block_modes[scb->block_mode].is_dual_plane;
212
213 int weight_quantization_level = bsd->block_modes[scb->block_mode].quantization_mode;
214
215 // decode the color endpoints
216 uint4 color_endpoint0[4];
217 uint4 color_endpoint1[4];
218 int rgb_hdr_endpoint[4];
219 int alpha_hdr_endpoint[4];
220 int nan_endpoint[4];
221
222 for (i = 0; i < partition_count; i++)
223 unpack_color_endpoints(decode_mode,
224 scb->color_formats[i],
225 scb->color_quantization_level,
226 scb->color_values[i],
227 &(rgb_hdr_endpoint[i]),
228 &(alpha_hdr_endpoint[i]),
229 &(nan_endpoint[i]),
230 &(color_endpoint0[i]),
231 &(color_endpoint1[i]));
232
233 // first unquantize the weights
234 int uq_plane1_weights[MAX_WEIGHTS_PER_BLOCK];
235 int uq_plane2_weights[MAX_WEIGHTS_PER_BLOCK];
236 int weight_count = it->num_weights;
237
238 const quantization_and_transfer_table *qat = &(quant_and_xfer_tables[weight_quantization_level]);
239
240 for (i = 0; i < weight_count; i++)
241 {
242 uq_plane1_weights[i] = qat->unquantized_value[scb->plane1_weights[i]];
243 }
244
245 if (is_dual_plane)
246 {
247 for (i = 0; i < weight_count; i++)
248 uq_plane2_weights[i] = qat->unquantized_value[scb->plane2_weights[i]];
249 }
250
251 // then undecimate them.
252 int weights[MAX_TEXELS_PER_BLOCK];
253 int plane2_weights[MAX_TEXELS_PER_BLOCK];
254
255 for (i = 0; i < bsd->texel_count; i++)
256 weights[i] = compute_value_of_texel_int(i, it, uq_plane1_weights);
257
258 if (is_dual_plane)
259 for (i = 0; i < bsd->texel_count; i++)
260 plane2_weights[i] = compute_value_of_texel_int(i, it, uq_plane2_weights);
261
262 int plane2_color_component = scb->plane2_color_component;
263
264 // now that we have endpoint colors and weights, we can unpack actual colors for
265 // each texel.
266 for (i = 0; i < bsd->texel_count; i++)
267 {
268 int partition = pt->partition_of_texel[i];
269
270 uint4 color = lerp_color_int(decode_mode,
271 color_endpoint0[partition],
272 color_endpoint1[partition],
273 weights[i],
274 plane2_weights[i],
275 is_dual_plane ? plane2_color_component : -1);
276
277 blk->rgb_lns[i] = rgb_hdr_endpoint[partition];
278 blk->alpha_lns[i] = alpha_hdr_endpoint[partition];
279 blk->nan_texel[i] = nan_endpoint[partition];
280
281 blk->data_r[i] = (float)color.x;
282 blk->data_g[i] = (float)color.y;
283 blk->data_b[i] = (float)color.z;
284 blk->data_a[i] = (float)color.w;
285 }
286
287 imageblock_initialize_orig_from_work(blk, bsd->texel_count);
288
289 update_imageblock_flags(blk, bsd->xdim, bsd->ydim, bsd->zdim);
290 }
291