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