• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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