1 // SPDX-License-Identifier: Apache-2.0
2 // ----------------------------------------------------------------------------
3 // Copyright 2011-2021 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 #include <utility>
19 
20 /**
21  * @brief Functions for color unquantization.
22  */
23 
24 #include "astcenc_internal.h"
25 
26 /**
27  * @brief Unquantize a color.
28  *
29  * This function uses a lookup table as the quantization is encoded to make
30  * hardware implementations easier, and is not a simple lerp.
31  *
32  * @param quant_level   The quantization level to use.
33  * @param inputq        The input quantized color.
34  *
35  * @return The unquantized color.
36  */
unquant_color(quant_method quant_level,vint4 inputq)37 static ASTCENC_SIMD_INLINE vint4 unquant_color(
38 	quant_method quant_level,
39 	vint4 inputq
40 ) {
41 	const uint8_t* unq = color_unquant_tables[quant_level - QUANT_6];
42 	return vint4(unq[inputq.lane<0>()], unq[inputq.lane<1>()],
43 	             unq[inputq.lane<2>()], unq[inputq.lane<3>()]);
44 }
45 
46 /**
47  * @brief Determine the quantized value given a quantization level.
48  *
49  * @param quant_level   The quantization level to use.
50  * @param value         The value to convert. This may be outside of the 0-255 range and will be
51  *                      clamped before the value is looked up.
52  *
53  * @return The encoded quantized value. These are not necessarily in order; the compressor
54  *         scrambles the values slightly to make hardware implementation easier.
55  */
unquant_color(quant_method quant_level,int value)56 static inline uint8_t unquant_color(
57 	quant_method quant_level,
58 	int value
59 ) {
60 	return color_unquant_tables[quant_level - QUANT_6][value];
61 }
62 
63 /**
64  * @brief Un-blue-contract a color.
65  *
66  * This function reverses any applied blue contraction.
67  *
68  * @param input   The input color that has been blue-contracted.
69  *
70  * @return The uncontracted color.
71  */
uncontract_color(vint4 input)72 static ASTCENC_SIMD_INLINE vint4 uncontract_color(
73 	vint4 input
74 ) {
75 	vmask4 mask(true, true, false, false);
76 	vint4 bc0 = asr<1>(input + input.lane<2>());
77 	return select(input, bc0, mask);
78 }
79 
80 /**
81  * @brief Unpack an LDR RGBA color that uses delta encoding.
82  *
83  * @param      input0q       The raw quantized endpoint 0 color.
84  * @param      input1q       The raw quantized endpoint 1 color deltas.
85  * @param      quant_level   The quantization level to use.
86  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
87  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
88  */
rgba_delta_unpack(vint4 input0q,vint4 input1q,quant_method quant_level,vint4 & output0,vint4 & output1)89 static void rgba_delta_unpack(
90 	vint4 input0q,
91 	vint4 input1q,
92 	quant_method quant_level,
93 	vint4& output0,
94 	vint4& output1
95 ) {
96 	// Unquantize color endpoints
97 	vint4 input0 = unquant_color(quant_level, input0q);
98 	vint4 input1 = unquant_color(quant_level, input1q);
99 
100 	// Apply bit transfer
101 	bit_transfer_signed(input1, input0);
102 
103 	// Apply blue-uncontraction if needed
104 	int rgb_sum = hadd_rgb_s(input1);
105 	input1 = input1 + input0;
106 	if (rgb_sum < 0)
107 	{
108 		input0 = uncontract_color(input0);
109 		input1 = uncontract_color(input1);
110 		std::swap(input0, input1);
111 	}
112 
113 	output0 = clamp(0, 255, input0);
114 	output1 = clamp(0, 255, input1);
115 }
116 
117 /**
118  * @brief Unpack an LDR RGB color that uses delta encoding.
119  *
120  * Output alpha set to 255.
121  *
122  * @param      input0q       The raw quantized endpoint 0 color.
123  * @param      input1q       The raw quantized endpoint 1 color deltas.
124  * @param      quant_level   The quantization level to use.
125  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
126  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
127  */
rgb_delta_unpack(vint4 input0q,vint4 input1q,quant_method quant_level,vint4 & output0,vint4 & output1)128 static void rgb_delta_unpack(
129 	vint4 input0q,
130 	vint4 input1q,
131 	quant_method quant_level,
132 	vint4& output0,
133 	vint4& output1
134 ) {
135 	rgba_delta_unpack(input0q, input1q, quant_level, output0, output1);
136 	output0.set_lane<3>(255);
137 	output1.set_lane<3>(255);
138 }
139 
140 /**
141  * @brief Unpack an LDR RGBA color that uses direct encoding.
142  *
143  * @param      input0q       The raw quantized endpoint 0 color.
144  * @param      input1q       The raw quantized endpoint 1 color.
145  * @param      quant_level   The quantization level to use.
146  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
147  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
148  */
rgba_unpack(vint4 input0q,vint4 input1q,quant_method quant_level,vint4 & output0,vint4 & output1)149 static void rgba_unpack(
150 	vint4 input0q,
151 	vint4 input1q,
152 	quant_method quant_level,
153 	vint4& output0,
154 	vint4& output1
155 ) {
156 	// Unquantize color endpoints
157 	vint4 input0 = unquant_color(quant_level, input0q);
158 	vint4 input1 = unquant_color(quant_level, input1q);
159 
160 	// Apply blue-uncontraction if needed
161 	if (hadd_rgb_s(input0) > hadd_rgb_s(input1))
162 	{
163 		input0 = uncontract_color(input0);
164 		input1 = uncontract_color(input1);
165 		std::swap(input0, input1);
166 	}
167 
168 	output0 = input0;
169 	output1 = input1;
170 }
171 
172 /**
173  * @brief Unpack an LDR RGB color that uses direct encoding.
174  *
175  * Output alpha set to 255.
176  *
177  * @param      input0q       The raw quantized endpoint 0 color.
178  * @param      input1q       The raw quantized endpoint 1 color.
179  * @param      quant_level   The quantization level to use.
180  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
181  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
182  */
rgb_unpack(vint4 input0q,vint4 input1q,quant_method quant_level,vint4 & output0,vint4 & output1)183 static void rgb_unpack(
184 	vint4 input0q,
185 	vint4 input1q,
186 	quant_method quant_level,
187 	vint4& output0,
188 	vint4& output1
189 ) {
190 	rgba_unpack(input0q, input1q, quant_level, output0, output1);
191 	output0.set_lane<3>(255);
192 	output1.set_lane<3>(255);
193 }
194 
195 /**
196  * @brief Unpack an LDR RGBA color that uses scaled encoding.
197  *
198  * Note only the RGB channels use the scaled encoding, alpha uses direct.
199  *
200  * @param      input0q       The raw quantized endpoint 0 color.
201  * @param      alpha1q       The raw quantized endpoint 1 alpha value.
202  * @param      scaleq        The raw quantized scale.
203  * @param      quant_level   The quantization level to use.
204  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
205  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
206  */
rgb_scale_alpha_unpack(vint4 input0q,uint8_t alpha1q,uint8_t scaleq,quant_method quant_level,vint4 & output0,vint4 & output1)207 static void rgb_scale_alpha_unpack(
208 	vint4 input0q,
209 	uint8_t alpha1q,
210 	uint8_t scaleq,
211 	quant_method quant_level,
212 	vint4& output0,
213 	vint4& output1
214 ) {
215 	// Unquantize color endpoints
216 	vint4 input = unquant_color(quant_level, input0q);
217 	uint8_t alpha1 = unquant_color(quant_level, alpha1q);
218 	uint8_t scale = unquant_color(quant_level, scaleq);
219 
220 	output1 = input;
221 	output1.set_lane<3>(alpha1);
222 
223 	output0 = asr<8>(input * scale);
224 	output0.set_lane<3>(input.lane<3>());
225 }
226 
227 /**
228  * @brief Unpack an LDR RGB color that uses scaled encoding.
229  *
230  * Output alpha is 255.
231  *
232  * @param      input0q       The raw quantized endpoint 0 color.
233  * @param      scaleq        The raw quantized scale.
234  * @param      quant_level   The quantization level to use.
235  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
236  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
237  */
rgb_scale_unpack(vint4 input0q,int scaleq,quant_method quant_level,vint4 & output0,vint4 & output1)238 static void rgb_scale_unpack(
239 	vint4 input0q,
240 	int scaleq,
241 	quant_method quant_level,
242 	vint4& output0,
243 	vint4& output1
244 ) {
245 	vint4 input = unquant_color(quant_level, input0q);
246 	int scale = unquant_color(quant_level, scaleq);
247 
248 	output1 = input;
249 	output1.set_lane<3>(255);
250 
251 	output0 = asr<8>(input * scale);
252 	output0.set_lane<3>(255);
253 }
254 
255 /**
256  * @brief Unpack an LDR L color that uses direct encoding.
257  *
258  * Output alpha is 255.
259  *
260  * @param      input         The raw quantized endpoints.
261  * @param      quant_level   The quantization level to use.
262  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
263  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
264  */
luminance_unpack(const uint8_t input[2],quant_method quant_level,vint4 & output0,vint4 & output1)265 static void luminance_unpack(
266 	const uint8_t input[2],
267 	quant_method quant_level,
268 	vint4& output0,
269 	vint4& output1
270 ) {
271 	int lum0 = unquant_color(quant_level, input[0]);
272 	int lum1 = unquant_color(quant_level, input[1]);
273 	output0 = vint4(lum0, lum0, lum0, 255);
274 	output1 = vint4(lum1, lum1, lum1, 255);
275 }
276 
277 /**
278  * @brief Unpack an LDR L color that uses delta encoding.
279  *
280  * Output alpha is 255.
281  *
282  * @param      input         The raw quantized endpoints (L0, L1).
283  * @param      quant_level   The quantization level to use.
284  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
285  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
286  */
luminance_delta_unpack(const uint8_t input[2],quant_method quant_level,vint4 & output0,vint4 & output1)287 static void luminance_delta_unpack(
288 	const uint8_t input[2],
289 	quant_method quant_level,
290 	vint4& output0,
291 	vint4& output1
292 ) {
293 	int v0 = unquant_color(quant_level, input[0]);
294 	int v1 = unquant_color(quant_level, input[1]);
295 	int l0 = (v0 >> 2) | (v1 & 0xC0);
296 	int l1 = l0 + (v1 & 0x3F);
297 
298 	l1 = astc::min(l1, 255);
299 
300 	output0 = vint4(l0, l0, l0, 255);
301 	output1 = vint4(l1, l1, l1, 255);
302 }
303 
304 /**
305  * @brief Unpack an LDR LA color that uses direct encoding.
306  *
307  * @param      input         The raw quantized endpoints (L0, L1, A0, A1).
308  * @param      quant_level   The quantization level to use.
309  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
310  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
311  */
luminance_alpha_unpack(const uint8_t input[4],quant_method quant_level,vint4 & output0,vint4 & output1)312 static void luminance_alpha_unpack(
313 	const uint8_t input[4],
314 	quant_method quant_level,
315 	vint4& output0,
316 	vint4& output1
317 ) {
318 	int lum0 =   unquant_color(quant_level, input[0]);
319 	int lum1 =   unquant_color(quant_level, input[1]);
320 	int alpha0 = unquant_color(quant_level, input[2]);
321 	int alpha1 = unquant_color(quant_level, input[3]);
322 	output0 = vint4(lum0, lum0, lum0, alpha0);
323 	output1 = vint4(lum1, lum1, lum1, alpha1);
324 }
325 
326 /**
327  * @brief Unpack an LDR LA color that uses delta encoding.
328  *
329  * @param      input         The raw quantized endpoints (L0, L1, A0, A1).
330  * @param      quant_level   The quantization level to use.
331  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
332  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
333  */
luminance_alpha_delta_unpack(const uint8_t input[4],quant_method quant_level,vint4 & output0,vint4 & output1)334 static void luminance_alpha_delta_unpack(
335 	const uint8_t input[4],
336 	quant_method quant_level,
337 	vint4& output0,
338 	vint4& output1
339 ) {
340 	int lum0 =   unquant_color(quant_level, input[0]);
341 	int lum1 =   unquant_color(quant_level, input[1]);
342 	int alpha0 = unquant_color(quant_level, input[2]);
343 	int alpha1 = unquant_color(quant_level, input[3]);
344 
345 	lum0 |= (lum1 & 0x80) << 1;
346 	alpha0 |= (alpha1 & 0x80) << 1;
347 	lum1 &= 0x7F;
348 	alpha1 &= 0x7F;
349 	if (lum1 & 0x40)
350 		lum1 -= 0x80;
351 	if (alpha1 & 0x40)
352 		alpha1 -= 0x80;
353 
354 	lum0 >>= 1;
355 	lum1 >>= 1;
356 	alpha0 >>= 1;
357 	alpha1 >>= 1;
358 	lum1 += lum0;
359 	alpha1 += alpha0;
360 
361 	lum1 = astc::clamp(lum1, 0, 255);
362 	alpha1 = astc::clamp(alpha1, 0, 255);
363 
364 	output0 = vint4(lum0, lum0, lum0, alpha0);
365 	output1 = vint4(lum1, lum1, lum1, alpha1);
366 }
367 
368 /**
369  * @brief Unpack an HDR RGB + offset encoding.
370  *
371  * @param      input         The raw quantized endpoints (packed and modal).
372  * @param      quant_level   The quantization level to use.
373  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
374  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
375  */
hdr_rgbo_unpack(const uint8_t input[4],quant_method quant_level,vint4 & output0,vint4 & output1)376 static void hdr_rgbo_unpack(
377 	const uint8_t input[4],
378 	quant_method quant_level,
379 	vint4& output0,
380 	vint4& output1
381 ) {
382 	int v0 = unquant_color(quant_level, input[0]);
383 	int v1 = unquant_color(quant_level, input[1]);
384 	int v2 = unquant_color(quant_level, input[2]);
385 	int v3 = unquant_color(quant_level, input[3]);
386 
387 	int modeval = ((v0 & 0xC0) >> 6) | (((v1 & 0x80) >> 7) << 2) | (((v2 & 0x80) >> 7) << 3);
388 
389 	int majcomp;
390 	int mode;
391 	if ((modeval & 0xC) != 0xC)
392 	{
393 		majcomp = modeval >> 2;
394 		mode = modeval & 3;
395 	}
396 	else if (modeval != 0xF)
397 	{
398 		majcomp = modeval & 3;
399 		mode = 4;
400 	}
401 	else
402 	{
403 		majcomp = 0;
404 		mode = 5;
405 	}
406 
407 	int red = v0 & 0x3F;
408 	int green = v1 & 0x1F;
409 	int blue = v2 & 0x1F;
410 	int scale = v3 & 0x1F;
411 
412 	int bit0 = (v1 >> 6) & 1;
413 	int bit1 = (v1 >> 5) & 1;
414 	int bit2 = (v2 >> 6) & 1;
415 	int bit3 = (v2 >> 5) & 1;
416 	int bit4 = (v3 >> 7) & 1;
417 	int bit5 = (v3 >> 6) & 1;
418 	int bit6 = (v3 >> 5) & 1;
419 
420 	int ohcomp = 1 << mode;
421 
422 	if (ohcomp & 0x30)
423 		green |= bit0 << 6;
424 	if (ohcomp & 0x3A)
425 		green |= bit1 << 5;
426 	if (ohcomp & 0x30)
427 		blue |= bit2 << 6;
428 	if (ohcomp & 0x3A)
429 		blue |= bit3 << 5;
430 
431 	if (ohcomp & 0x3D)
432 		scale |= bit6 << 5;
433 	if (ohcomp & 0x2D)
434 		scale |= bit5 << 6;
435 	if (ohcomp & 0x04)
436 		scale |= bit4 << 7;
437 
438 	if (ohcomp & 0x3B)
439 		red |= bit4 << 6;
440 	if (ohcomp & 0x04)
441 		red |= bit3 << 6;
442 
443 	if (ohcomp & 0x10)
444 		red |= bit5 << 7;
445 	if (ohcomp & 0x0F)
446 		red |= bit2 << 7;
447 
448 	if (ohcomp & 0x05)
449 		red |= bit1 << 8;
450 	if (ohcomp & 0x0A)
451 		red |= bit0 << 8;
452 
453 	if (ohcomp & 0x05)
454 		red |= bit0 << 9;
455 	if (ohcomp & 0x02)
456 		red |= bit6 << 9;
457 
458 	if (ohcomp & 0x01)
459 		red |= bit3 << 10;
460 	if (ohcomp & 0x02)
461 		red |= bit5 << 10;
462 
463 	// expand to 12 bits.
464 	static const int shamts[6] { 1, 1, 2, 3, 4, 5 };
465 	int shamt = shamts[mode];
466 	red <<= shamt;
467 	green <<= shamt;
468 	blue <<= shamt;
469 	scale <<= shamt;
470 
471 	// on modes 0 to 4, the values stored for "green" and "blue" are differentials,
472 	// not absolute values.
473 	if (mode != 5)
474 	{
475 		green = red - green;
476 		blue = red - blue;
477 	}
478 
479 	// switch around components.
480 	int temp;
481 	switch (majcomp)
482 	{
483 	case 1:
484 		temp = red;
485 		red = green;
486 		green = temp;
487 		break;
488 	case 2:
489 		temp = red;
490 		red = blue;
491 		blue = temp;
492 		break;
493 	default:
494 		break;
495 	}
496 
497 	int red0 = red - scale;
498 	int green0 = green - scale;
499 	int blue0 = blue - scale;
500 
501 	// clamp to [0,0xFFF].
502 	if (red < 0)
503 		red = 0;
504 	if (green < 0)
505 		green = 0;
506 	if (blue < 0)
507 		blue = 0;
508 
509 	if (red0 < 0)
510 		red0 = 0;
511 	if (green0 < 0)
512 		green0 = 0;
513 	if (blue0 < 0)
514 		blue0 = 0;
515 
516 	output0 = vint4(red0 << 4, green0 << 4, blue0 << 4, 0x7800);
517 	output1 = vint4(red << 4, green << 4, blue << 4, 0x7800);
518 }
519 
520 /**
521  * @brief Unpack an HDR RGB direct encoding.
522  *
523  * @param      input         The raw quantized endpoints (packed and modal).
524  * @param      quant_level   The quantization level to use.
525  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
526  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
527  */
hdr_rgb_unpack(const uint8_t input[6],quant_method quant_level,vint4 & output0,vint4 & output1)528 static void hdr_rgb_unpack(
529 	const uint8_t input[6],
530 	quant_method quant_level,
531 	vint4& output0,
532 	vint4& output1
533 ) {
534 
535 	int v0 = unquant_color(quant_level, input[0]);
536 	int v1 = unquant_color(quant_level, input[1]);
537 	int v2 = unquant_color(quant_level, input[2]);
538 	int v3 = unquant_color(quant_level, input[3]);
539 	int v4 = unquant_color(quant_level, input[4]);
540 	int v5 = unquant_color(quant_level, input[5]);
541 
542 	// extract all the fixed-placement bitfields
543 	int modeval = ((v1 & 0x80) >> 7) | (((v2 & 0x80) >> 7) << 1) | (((v3 & 0x80) >> 7) << 2);
544 
545 	int majcomp = ((v4 & 0x80) >> 7) | (((v5 & 0x80) >> 7) << 1);
546 
547 	if (majcomp == 3)
548 	{
549 		output0 = vint4(v0 << 8, v2 << 8, (v4 & 0x7F) << 9, 0x7800);
550 		output1 = vint4(v1 << 8, v3 << 8, (v5 & 0x7F) << 9, 0x7800);
551 		return;
552 	}
553 
554 	int a = v0 | ((v1 & 0x40) << 2);
555 	int b0 = v2 & 0x3f;
556 	int b1 = v3 & 0x3f;
557 	int c = v1 & 0x3f;
558 	int d0 = v4 & 0x7f;
559 	int d1 = v5 & 0x7f;
560 
561 	// get hold of the number of bits in 'd0' and 'd1'
562 	static const int dbits_tab[8] { 7, 6, 7, 6, 5, 6, 5, 6 };
563 	int dbits = dbits_tab[modeval];
564 
565 	// extract six variable-placement bits
566 	int bit0 = (v2 >> 6) & 1;
567 	int bit1 = (v3 >> 6) & 1;
568 	int bit2 = (v4 >> 6) & 1;
569 	int bit3 = (v5 >> 6) & 1;
570 	int bit4 = (v4 >> 5) & 1;
571 	int bit5 = (v5 >> 5) & 1;
572 
573 	// and prepend the variable-placement bits depending on mode.
574 	int ohmod = 1 << modeval;	// one-hot-mode
575 	if (ohmod & 0xA4)
576 		a |= bit0 << 9;
577 	if (ohmod & 0x8)
578 		a |= bit2 << 9;
579 	if (ohmod & 0x50)
580 		a |= bit4 << 9;
581 
582 	if (ohmod & 0x50)
583 		a |= bit5 << 10;
584 	if (ohmod & 0xA0)
585 		a |= bit1 << 10;
586 
587 	if (ohmod & 0xC0)
588 		a |= bit2 << 11;
589 
590 	if (ohmod & 0x4)
591 		c |= bit1 << 6;
592 	if (ohmod & 0xE8)
593 		c |= bit3 << 6;
594 
595 	if (ohmod & 0x20)
596 		c |= bit2 << 7;
597 
598 	if (ohmod & 0x5B)
599 	{
600 		b0 |= bit0 << 6;
601 		b1 |= bit1 << 6;
602 	}
603 
604 	if (ohmod & 0x12)
605 	{
606 		b0 |= bit2 << 7;
607 		b1 |= bit3 << 7;
608 	}
609 
610 	if (ohmod & 0xAF)
611 	{
612 		d0 |= bit4 << 5;
613 		d1 |= bit5 << 5;
614 	}
615 
616 	if (ohmod & 0x5)
617 	{
618 		d0 |= bit2 << 6;
619 		d1 |= bit3 << 6;
620 	}
621 
622 	// sign-extend 'd0' and 'd1'
623 	// note: this code assumes that signed right-shift actually sign-fills, not zero-fills.
624 	int32_t d0x = d0;
625 	int32_t d1x = d1;
626 	int sx_shamt = 32 - dbits;
627 	d0x <<= sx_shamt;
628 	d0x >>= sx_shamt;
629 	d1x <<= sx_shamt;
630 	d1x >>= sx_shamt;
631 	d0 = d0x;
632 	d1 = d1x;
633 
634 	// expand all values to 12 bits, with left-shift as needed.
635 	int val_shamt = (modeval >> 1) ^ 3;
636 	a <<= val_shamt;
637 	b0 <<= val_shamt;
638 	b1 <<= val_shamt;
639 	c <<= val_shamt;
640 	d0 <<= val_shamt;
641 	d1 <<= val_shamt;
642 
643 	// then compute the actual color values.
644 	int red1 = a;
645 	int green1 = a - b0;
646 	int blue1 = a - b1;
647 	int red0 = a - c;
648 	int green0 = a - b0 - c - d0;
649 	int blue0 = a - b1 - c - d1;
650 
651 	// clamp the color components to [0,2^12 - 1]
652 	red0 = astc::clamp(red0, 0, 4095);
653 	green0 = astc::clamp(green0, 0, 4095);
654 	blue0 = astc::clamp(blue0, 0, 4095);
655 
656 	red1 = astc::clamp(red1, 0, 4095);
657 	green1 = astc::clamp(green1, 0, 4095);
658 	blue1 = astc::clamp(blue1, 0, 4095);
659 
660 	// switch around the color components
661 	int temp0, temp1;
662 	switch (majcomp)
663 	{
664 	case 1:					// switch around red and green
665 		temp0 = red0;
666 		temp1 = red1;
667 		red0 = green0;
668 		red1 = green1;
669 		green0 = temp0;
670 		green1 = temp1;
671 		break;
672 	case 2:					// switch around red and blue
673 		temp0 = red0;
674 		temp1 = red1;
675 		red0 = blue0;
676 		red1 = blue1;
677 		blue0 = temp0;
678 		blue1 = temp1;
679 		break;
680 	case 0:					// no switch
681 		break;
682 	}
683 
684 	output0 = vint4(red0 << 4, green0 << 4, blue0 << 4, 0x7800);
685 	output1 = vint4(red1 << 4, green1 << 4, blue1 << 4, 0x7800);
686 }
687 
688 /**
689  * @brief Unpack an HDR RGB + LDR A direct encoding.
690  *
691  * @param      input         The raw quantized endpoints (packed and modal).
692  * @param      quant_level   The quantization level to use.
693  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
694  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
695  */
hdr_rgb_ldr_alpha_unpack(const uint8_t input[8],quant_method quant_level,vint4 & output0,vint4 & output1)696 static void hdr_rgb_ldr_alpha_unpack(
697 	const uint8_t input[8],
698 	quant_method quant_level,
699 	vint4& output0,
700 	vint4& output1
701 ) {
702 	hdr_rgb_unpack(input, quant_level, output0, output1);
703 
704 	int v6 = unquant_color(quant_level, input[6]);
705 	int v7 = unquant_color(quant_level, input[7]);
706 	output0.set_lane<3>(v6);
707 	output1.set_lane<3>(v7);
708 }
709 
710 /**
711  * @brief Unpack an HDR L (small range) direct encoding.
712  *
713  * @param      input         The raw quantized endpoints (packed and modal).
714  * @param      quant_level   The quantization level to use.
715  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
716  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
717  */
hdr_luminance_small_range_unpack(const uint8_t input[2],quant_method quant_level,vint4 & output0,vint4 & output1)718 static void hdr_luminance_small_range_unpack(
719 	const uint8_t input[2],
720 	quant_method quant_level,
721 	vint4& output0,
722 	vint4& output1
723 ) {
724 	int v0 = unquant_color(quant_level, input[0]);
725 	int v1 = unquant_color(quant_level, input[1]);
726 
727 	int y0, y1;
728 	if (v0 & 0x80)
729 	{
730 		y0 = ((v1 & 0xE0) << 4) | ((v0 & 0x7F) << 2);
731 		y1 = (v1 & 0x1F) << 2;
732 	}
733 	else
734 	{
735 		y0 = ((v1 & 0xF0) << 4) | ((v0 & 0x7F) << 1);
736 		y1 = (v1 & 0xF) << 1;
737 	}
738 
739 	y1 += y0;
740 	if (y1 > 0xFFF)
741 		y1 = 0xFFF;
742 
743 	output0 = vint4(y0 << 4, y0 << 4, y0 << 4, 0x7800);
744 	output1 = vint4(y1 << 4, y1 << 4, y1 << 4, 0x7800);
745 }
746 
747 /**
748  * @brief Unpack an HDR L (large range) direct encoding.
749  *
750  * @param      input         The raw quantized endpoints (packed and modal).
751  * @param      quant_level   The quantization level to use.
752  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
753  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
754  */
hdr_luminance_large_range_unpack(const uint8_t input[2],quant_method quant_level,vint4 & output0,vint4 & output1)755 static void hdr_luminance_large_range_unpack(
756 	const uint8_t input[2],
757 	quant_method quant_level,
758 	vint4& output0,
759 	vint4& output1
760 ) {
761 	int v0 = unquant_color(quant_level, input[0]);
762 	int v1 = unquant_color(quant_level, input[1]);
763 
764 	int y0, y1;
765 	if (v1 >= v0)
766 	{
767 		y0 = v0 << 4;
768 		y1 = v1 << 4;
769 	}
770 	else
771 	{
772 		y0 = (v1 << 4) + 8;
773 		y1 = (v0 << 4) - 8;
774 	}
775 
776 	output0 = vint4(y0 << 4, y0 << 4, y0 << 4, 0x7800);
777 	output1 = vint4(y1 << 4, y1 << 4, y1 << 4, 0x7800);
778 }
779 
780 /**
781  * @brief Unpack an HDR A direct encoding.
782  *
783  * @param      input         The raw quantized endpoints (packed and modal).
784  * @param      quant_level   The quantization level to use.
785  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
786  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
787  */
hdr_alpha_unpack(const uint8_t input[2],quant_method quant_level,int & output0,int & output1)788 static void hdr_alpha_unpack(
789 	const uint8_t input[2],
790 	quant_method quant_level,
791 	int& output0,
792 	int& output1
793 ) {
794 
795 	int v6 = unquant_color(quant_level, input[0]);
796 	int v7 = unquant_color(quant_level, input[1]);
797 
798 	int selector = ((v6 >> 7) & 1) | ((v7 >> 6) & 2);
799 	v6 &= 0x7F;
800 	v7 &= 0x7F;
801 	if (selector == 3)
802 	{
803 		output0 = v6 << 5;
804 		output1 = v7 << 5;
805 	}
806 	else
807 	{
808 		v6 |= (v7 << (selector + 1)) & 0x780;
809 		v7 &= (0x3f >> selector);
810 		v7 ^= 32 >> selector;
811 		v7 -= 32 >> selector;
812 		v6 <<= (4 - selector);
813 		v7 <<= (4 - selector);
814 		v7 += v6;
815 
816 		if (v7 < 0)
817 			v7 = 0;
818 		else if (v7 > 0xFFF)
819 			v7 = 0xFFF;
820 
821 		output0 = v6;
822 		output1 = v7;
823 	}
824 
825 	output0 <<= 4;
826 	output1 <<= 4;
827 }
828 
829 /**
830  * @brief Unpack an HDR RGBA direct encoding.
831  *
832  * @param      input         The raw quantized endpoints (packed and modal).
833  * @param      quant_level   The quantization level to use.
834  * @param[out] output0       The unpacked and unquantized endpoint 0 color.
835  * @param[out] output1       The unpacked and unquantized endpoint 1 color.
836  */
hdr_rgb_hdr_alpha_unpack(const uint8_t input[8],quant_method quant_level,vint4 & output0,vint4 & output1)837 static void hdr_rgb_hdr_alpha_unpack(
838 	const uint8_t input[8],
839 	quant_method quant_level,
840 	vint4& output0,
841 	vint4& output1
842 ) {
843 	hdr_rgb_unpack(input, quant_level, output0, output1);
844 
845 	int alpha0, alpha1;
846 	hdr_alpha_unpack(input + 6, quant_level, alpha0, alpha1);
847 
848 	output0.set_lane<3>(alpha0);
849 	output1.set_lane<3>(alpha1);
850 }
851 
852 /* See header for documentation. */
unpack_color_endpoints(astcenc_profile decode_mode,int format,quant_method quant_level,const uint8_t * input,bool & rgb_hdr,bool & alpha_hdr,vint4 & output0,vint4 & output1)853 void unpack_color_endpoints(
854 	astcenc_profile decode_mode,
855 	int format,
856 	quant_method quant_level,
857 	const uint8_t* input,
858 	bool& rgb_hdr,
859 	bool& alpha_hdr,
860 	vint4& output0,
861 	vint4& output1
862 ) {
863 	// Assume no NaNs and LDR endpoints unless set later
864 	rgb_hdr = false;
865 	alpha_hdr = false;
866 
867 	bool alpha_hdr_default = false;
868 
869 	switch (format)
870 	{
871 	case FMT_LUMINANCE:
872 		luminance_unpack(input, quant_level, output0, output1);
873 		break;
874 
875 	case FMT_LUMINANCE_DELTA:
876 		luminance_delta_unpack(input, quant_level, output0, output1);
877 		break;
878 
879 	case FMT_HDR_LUMINANCE_SMALL_RANGE:
880 		rgb_hdr = true;
881 		alpha_hdr_default = true;
882 		hdr_luminance_small_range_unpack(input, quant_level, output0, output1);
883 		break;
884 
885 	case FMT_HDR_LUMINANCE_LARGE_RANGE:
886 		rgb_hdr = true;
887 		alpha_hdr_default = true;
888 		hdr_luminance_large_range_unpack(input, quant_level, output0, output1);
889 		break;
890 
891 	case FMT_LUMINANCE_ALPHA:
892 		luminance_alpha_unpack(input, quant_level, output0, output1);
893 		break;
894 
895 	case FMT_LUMINANCE_ALPHA_DELTA:
896 		luminance_alpha_delta_unpack(input, quant_level, output0, output1);
897 		break;
898 
899 	case FMT_RGB_SCALE:
900 		{
901 			vint4 input0q(input[0], input[1], input[2], 0);
902 			uint8_t scale = input[3];
903 			rgb_scale_unpack(input0q, scale, quant_level, output0, output1);
904 		}
905 		break;
906 
907 	case FMT_RGB_SCALE_ALPHA:
908 		{
909 			vint4 input0q(input[0], input[1], input[2], input[4]);
910 			uint8_t alpha1q = input[5];
911 			uint8_t scaleq = input[3];
912 			rgb_scale_alpha_unpack(input0q, alpha1q, scaleq, quant_level, output0, output1);
913 		}
914 		break;
915 
916 	case FMT_HDR_RGB_SCALE:
917 		rgb_hdr = true;
918 		alpha_hdr_default = true;
919 		hdr_rgbo_unpack(input, quant_level,output0, output1);
920 		break;
921 
922 	case FMT_RGB:
923 		{
924 			vint4 input0q(input[0], input[2], input[4], 0);
925 			vint4 input1q(input[1], input[3], input[5], 0);
926 			rgb_unpack(input0q, input1q, quant_level, output0, output1);
927 		}
928 		break;
929 
930 	case FMT_RGB_DELTA:
931 		{
932 			vint4 input0q(input[0], input[2], input[4], 0);
933 			vint4 input1q(input[1], input[3], input[5], 0);
934 			rgb_delta_unpack(input0q, input1q, quant_level, output0, output1);
935 		}
936 		break;
937 
938 	case FMT_HDR_RGB:
939 		rgb_hdr = true;
940 		alpha_hdr_default = true;
941 		hdr_rgb_unpack(input, quant_level, output0, output1);
942 		break;
943 
944 	case FMT_RGBA:
945 		{
946 			vint4 input0q(input[0], input[2], input[4], input[6]);
947 			vint4 input1q(input[1], input[3], input[5], input[7]);
948 			rgba_unpack(input0q, input1q, quant_level, output0, output1);
949 		}
950 		break;
951 
952 	case FMT_RGBA_DELTA:
953 		{
954 			vint4 input0q(input[0], input[2], input[4], input[6]);
955 			vint4 input1q(input[1], input[3], input[5], input[7]);
956 			rgba_delta_unpack(input0q, input1q, quant_level, output0, output1);
957 		}
958 		break;
959 
960 	case FMT_HDR_RGB_LDR_ALPHA:
961 		rgb_hdr = true;
962 		hdr_rgb_ldr_alpha_unpack(input, quant_level, output0, output1);
963 		break;
964 
965 	case FMT_HDR_RGBA:
966 		rgb_hdr = true;
967 		alpha_hdr = true;
968 		hdr_rgb_hdr_alpha_unpack(input, quant_level, output0, output1);
969 		break;
970 	}
971 
972 	// Assign a correct default alpha
973 	if (alpha_hdr_default)
974 	{
975 		if (decode_mode == ASTCENC_PRF_HDR)
976 		{
977 			output0.set_lane<3>(0x7800);
978 			output1.set_lane<3>(0x7800);
979 			alpha_hdr = true;
980 		}
981 		else
982 		{
983 			output0.set_lane<3>(0x00FF);
984 			output1.set_lane<3>(0x00FF);
985 			alpha_hdr = false;
986 		}
987 	}
988 
989 	vint4 ldr_scale(257);
990 	vint4 hdr_scale(1);
991 	vint4 output_scale = ldr_scale;
992 
993 	// An LDR profile image
994 	if ((decode_mode == ASTCENC_PRF_LDR) ||
995 	    (decode_mode == ASTCENC_PRF_LDR_SRGB))
996 	{
997 		// Also matches HDR alpha, as cannot have HDR alpha without HDR RGB
998 		if (rgb_hdr == true)
999 		{
1000 			output0 = vint4(0xFF00, 0x0000, 0xFF00, 0xFF00);
1001 			output1 = vint4(0xFF00, 0x0000, 0xFF00, 0xFF00);
1002 			output_scale = hdr_scale;
1003 
1004 			rgb_hdr = false;
1005 			alpha_hdr = false;
1006 		}
1007 	}
1008 	// An HDR profile image
1009 	else
1010 	{
1011 		vmask4 hdr_lanes(rgb_hdr, rgb_hdr, rgb_hdr, alpha_hdr);
1012 		output_scale = select(ldr_scale, hdr_scale, hdr_lanes);
1013 	}
1014 
1015 	output0 = output0 * output_scale;
1016 	output1 = output1 * output_scale;
1017 }
1018