summaryrefslogtreecommitdiffstats
path: root/thirdparty/astcenc/astcenc_color_unquantize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/astcenc/astcenc_color_unquantize.cpp')
-rw-r--r--thirdparty/astcenc/astcenc_color_unquantize.cpp941
1 files changed, 941 insertions, 0 deletions
diff --git a/thirdparty/astcenc/astcenc_color_unquantize.cpp b/thirdparty/astcenc/astcenc_color_unquantize.cpp
new file mode 100644
index 0000000000..d31895a627
--- /dev/null
+++ b/thirdparty/astcenc/astcenc_color_unquantize.cpp
@@ -0,0 +1,941 @@
+// SPDX-License-Identifier: Apache-2.0
+// ----------------------------------------------------------------------------
+// Copyright 2011-2021 Arm Limited
+//
+// Licensed under the Apache License, Version 2.0 (the "License"); you may not
+// use this file except in compliance with the License. You may obtain a copy
+// of the License at:
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+// License for the specific language governing permissions and limitations
+// under the License.
+// ----------------------------------------------------------------------------
+
+#include <utility>
+
+/**
+ * @brief Functions for color unquantization.
+ */
+
+#include "astcenc_internal.h"
+
+/**
+ * @brief Un-blue-contract a color.
+ *
+ * This function reverses any applied blue contraction.
+ *
+ * @param input The input color that has been blue-contracted.
+ *
+ * @return The uncontracted color.
+ */
+static ASTCENC_SIMD_INLINE vint4 uncontract_color(
+ vint4 input
+) {
+ vmask4 mask(true, true, false, false);
+ vint4 bc0 = asr<1>(input + input.lane<2>());
+ return select(input, bc0, mask);
+}
+
+/**
+ * @brief Unpack an LDR RGBA color that uses delta encoding.
+ *
+ * @param input0 The packed endpoint 0 color.
+ * @param input1 The packed endpoint 1 color deltas.
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void rgba_delta_unpack(
+ vint4 input0,
+ vint4 input1,
+ vint4& output0,
+ vint4& output1
+) {
+ // Apply bit transfer
+ bit_transfer_signed(input1, input0);
+
+ // Apply blue-uncontraction if needed
+ int rgb_sum = hadd_rgb_s(input1);
+ input1 = input1 + input0;
+ if (rgb_sum < 0)
+ {
+ input0 = uncontract_color(input0);
+ input1 = uncontract_color(input1);
+ std::swap(input0, input1);
+ }
+
+ output0 = clamp(0, 255, input0);
+ output1 = clamp(0, 255, input1);
+}
+
+/**
+ * @brief Unpack an LDR RGB color that uses delta encoding.
+ *
+ * Output alpha set to 255.
+ *
+ * @param input0 The packed endpoint 0 color.
+ * @param input1 The packed endpoint 1 color deltas.
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void rgb_delta_unpack(
+ vint4 input0,
+ vint4 input1,
+ vint4& output0,
+ vint4& output1
+) {
+ rgba_delta_unpack(input0, input1, output0, output1);
+ output0.set_lane<3>(255);
+ output1.set_lane<3>(255);
+}
+
+/**
+ * @brief Unpack an LDR RGBA color that uses direct encoding.
+ *
+ * @param input0 The packed endpoint 0 color.
+ * @param input1 The packed endpoint 1 color.
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void rgba_unpack(
+ vint4 input0,
+ vint4 input1,
+ vint4& output0,
+ vint4& output1
+) {
+ // Apply blue-uncontraction if needed
+ if (hadd_rgb_s(input0) > hadd_rgb_s(input1))
+ {
+ input0 = uncontract_color(input0);
+ input1 = uncontract_color(input1);
+ std::swap(input0, input1);
+ }
+
+ output0 = input0;
+ output1 = input1;
+}
+
+/**
+ * @brief Unpack an LDR RGB color that uses direct encoding.
+ *
+ * Output alpha set to 255.
+ *
+ * @param input0 The packed endpoint 0 color.
+ * @param input1 The packed endpoint 1 color.
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void rgb_unpack(
+ vint4 input0,
+ vint4 input1,
+ vint4& output0,
+ vint4& output1
+) {
+ rgba_unpack(input0, input1, output0, output1);
+ output0.set_lane<3>(255);
+ output1.set_lane<3>(255);
+}
+
+/**
+ * @brief Unpack an LDR RGBA color that uses scaled encoding.
+ *
+ * Note only the RGB channels use the scaled encoding, alpha uses direct.
+ *
+ * @param input0 The packed endpoint 0 color.
+ * @param alpha1 The packed endpoint 1 alpha value.
+ * @param scale The packed quantized scale.
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void rgb_scale_alpha_unpack(
+ vint4 input0,
+ uint8_t alpha1,
+ uint8_t scale,
+ vint4& output0,
+ vint4& output1
+) {
+ output1 = input0;
+ output1.set_lane<3>(alpha1);
+
+ output0 = asr<8>(input0 * scale);
+ output0.set_lane<3>(input0.lane<3>());
+}
+
+/**
+ * @brief Unpack an LDR RGB color that uses scaled encoding.
+ *
+ * Output alpha is 255.
+ *
+ * @param input0 The packed endpoint 0 color.
+ * @param scale The packed scale.
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void rgb_scale_unpack(
+ vint4 input0,
+ int scale,
+ vint4& output0,
+ vint4& output1
+) {
+ output1 = input0;
+ output1.set_lane<3>(255);
+
+ output0 = asr<8>(input0 * scale);
+ output0.set_lane<3>(255);
+}
+
+/**
+ * @brief Unpack an LDR L color that uses direct encoding.
+ *
+ * Output alpha is 255.
+ *
+ * @param input The packed endpoints.
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void luminance_unpack(
+ const uint8_t input[2],
+ vint4& output0,
+ vint4& output1
+) {
+ int lum0 = input[0];
+ int lum1 = input[1];
+ output0 = vint4(lum0, lum0, lum0, 255);
+ output1 = vint4(lum1, lum1, lum1, 255);
+}
+
+/**
+ * @brief Unpack an LDR L color that uses delta encoding.
+ *
+ * Output alpha is 255.
+ *
+ * @param input The packed endpoints (L0, L1).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void luminance_delta_unpack(
+ const uint8_t input[2],
+ vint4& output0,
+ vint4& output1
+) {
+ int v0 = input[0];
+ int v1 = input[1];
+ int l0 = (v0 >> 2) | (v1 & 0xC0);
+ int l1 = l0 + (v1 & 0x3F);
+
+ l1 = astc::min(l1, 255);
+
+ output0 = vint4(l0, l0, l0, 255);
+ output1 = vint4(l1, l1, l1, 255);
+}
+
+/**
+ * @brief Unpack an LDR LA color that uses direct encoding.
+ *
+ * @param input The packed endpoints (L0, L1, A0, A1).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void luminance_alpha_unpack(
+ const uint8_t input[4],
+ vint4& output0,
+ vint4& output1
+) {
+ int lum0 = input[0];
+ int lum1 = input[1];
+ int alpha0 = input[2];
+ int alpha1 = input[3];
+ output0 = vint4(lum0, lum0, lum0, alpha0);
+ output1 = vint4(lum1, lum1, lum1, alpha1);
+}
+
+/**
+ * @brief Unpack an LDR LA color that uses delta encoding.
+ *
+ * @param input The packed endpoints (L0, L1, A0, A1).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void luminance_alpha_delta_unpack(
+ const uint8_t input[4],
+ vint4& output0,
+ vint4& output1
+) {
+ int lum0 = input[0];
+ int lum1 = input[1];
+ int alpha0 = input[2];
+ int alpha1 = input[3];
+
+ lum0 |= (lum1 & 0x80) << 1;
+ alpha0 |= (alpha1 & 0x80) << 1;
+ lum1 &= 0x7F;
+ alpha1 &= 0x7F;
+
+ if (lum1 & 0x40)
+ {
+ lum1 -= 0x80;
+ }
+
+ if (alpha1 & 0x40)
+ {
+ alpha1 -= 0x80;
+ }
+
+ lum0 >>= 1;
+ lum1 >>= 1;
+ alpha0 >>= 1;
+ alpha1 >>= 1;
+ lum1 += lum0;
+ alpha1 += alpha0;
+
+ lum1 = astc::clamp(lum1, 0, 255);
+ alpha1 = astc::clamp(alpha1, 0, 255);
+
+ output0 = vint4(lum0, lum0, lum0, alpha0);
+ output1 = vint4(lum1, lum1, lum1, alpha1);
+}
+
+/**
+ * @brief Unpack an HDR RGB + offset encoding.
+ *
+ * @param input The packed endpoints (packed and modal).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void hdr_rgbo_unpack(
+ const uint8_t input[4],
+ vint4& output0,
+ vint4& output1
+) {
+ int v0 = input[0];
+ int v1 = input[1];
+ int v2 = input[2];
+ int v3 = input[3];
+
+ int modeval = ((v0 & 0xC0) >> 6) | (((v1 & 0x80) >> 7) << 2) | (((v2 & 0x80) >> 7) << 3);
+
+ int majcomp;
+ int mode;
+ if ((modeval & 0xC) != 0xC)
+ {
+ majcomp = modeval >> 2;
+ mode = modeval & 3;
+ }
+ else if (modeval != 0xF)
+ {
+ majcomp = modeval & 3;
+ mode = 4;
+ }
+ else
+ {
+ majcomp = 0;
+ mode = 5;
+ }
+
+ int red = v0 & 0x3F;
+ int green = v1 & 0x1F;
+ int blue = v2 & 0x1F;
+ int scale = v3 & 0x1F;
+
+ int bit0 = (v1 >> 6) & 1;
+ int bit1 = (v1 >> 5) & 1;
+ int bit2 = (v2 >> 6) & 1;
+ int bit3 = (v2 >> 5) & 1;
+ int bit4 = (v3 >> 7) & 1;
+ int bit5 = (v3 >> 6) & 1;
+ int bit6 = (v3 >> 5) & 1;
+
+ int ohcomp = 1 << mode;
+
+ if (ohcomp & 0x30)
+ green |= bit0 << 6;
+ if (ohcomp & 0x3A)
+ green |= bit1 << 5;
+ if (ohcomp & 0x30)
+ blue |= bit2 << 6;
+ if (ohcomp & 0x3A)
+ blue |= bit3 << 5;
+
+ if (ohcomp & 0x3D)
+ scale |= bit6 << 5;
+ if (ohcomp & 0x2D)
+ scale |= bit5 << 6;
+ if (ohcomp & 0x04)
+ scale |= bit4 << 7;
+
+ if (ohcomp & 0x3B)
+ red |= bit4 << 6;
+ if (ohcomp & 0x04)
+ red |= bit3 << 6;
+
+ if (ohcomp & 0x10)
+ red |= bit5 << 7;
+ if (ohcomp & 0x0F)
+ red |= bit2 << 7;
+
+ if (ohcomp & 0x05)
+ red |= bit1 << 8;
+ if (ohcomp & 0x0A)
+ red |= bit0 << 8;
+
+ if (ohcomp & 0x05)
+ red |= bit0 << 9;
+ if (ohcomp & 0x02)
+ red |= bit6 << 9;
+
+ if (ohcomp & 0x01)
+ red |= bit3 << 10;
+ if (ohcomp & 0x02)
+ red |= bit5 << 10;
+
+ // expand to 12 bits.
+ static const int shamts[6] { 1, 1, 2, 3, 4, 5 };
+ int shamt = shamts[mode];
+ red <<= shamt;
+ green <<= shamt;
+ blue <<= shamt;
+ scale <<= shamt;
+
+ // on modes 0 to 4, the values stored for "green" and "blue" are differentials,
+ // not absolute values.
+ if (mode != 5)
+ {
+ green = red - green;
+ blue = red - blue;
+ }
+
+ // switch around components.
+ int temp;
+ switch (majcomp)
+ {
+ case 1:
+ temp = red;
+ red = green;
+ green = temp;
+ break;
+ case 2:
+ temp = red;
+ red = blue;
+ blue = temp;
+ break;
+ default:
+ break;
+ }
+
+ int red0 = red - scale;
+ int green0 = green - scale;
+ int blue0 = blue - scale;
+
+ // clamp to [0,0xFFF].
+ if (red < 0)
+ red = 0;
+ if (green < 0)
+ green = 0;
+ if (blue < 0)
+ blue = 0;
+
+ if (red0 < 0)
+ red0 = 0;
+ if (green0 < 0)
+ green0 = 0;
+ if (blue0 < 0)
+ blue0 = 0;
+
+ output0 = vint4(red0 << 4, green0 << 4, blue0 << 4, 0x7800);
+ output1 = vint4(red << 4, green << 4, blue << 4, 0x7800);
+}
+
+/**
+ * @brief Unpack an HDR RGB direct encoding.
+ *
+ * @param input The packed endpoints (packed and modal).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void hdr_rgb_unpack(
+ const uint8_t input[6],
+ vint4& output0,
+ vint4& output1
+) {
+
+ int v0 = input[0];
+ int v1 = input[1];
+ int v2 = input[2];
+ int v3 = input[3];
+ int v4 = input[4];
+ int v5 = input[5];
+
+ // extract all the fixed-placement bitfields
+ int modeval = ((v1 & 0x80) >> 7) | (((v2 & 0x80) >> 7) << 1) | (((v3 & 0x80) >> 7) << 2);
+
+ int majcomp = ((v4 & 0x80) >> 7) | (((v5 & 0x80) >> 7) << 1);
+
+ if (majcomp == 3)
+ {
+ output0 = vint4(v0 << 8, v2 << 8, (v4 & 0x7F) << 9, 0x7800);
+ output1 = vint4(v1 << 8, v3 << 8, (v5 & 0x7F) << 9, 0x7800);
+ return;
+ }
+
+ int a = v0 | ((v1 & 0x40) << 2);
+ int b0 = v2 & 0x3f;
+ int b1 = v3 & 0x3f;
+ int c = v1 & 0x3f;
+ int d0 = v4 & 0x7f;
+ int d1 = v5 & 0x7f;
+
+ // get hold of the number of bits in 'd0' and 'd1'
+ static const int dbits_tab[8] { 7, 6, 7, 6, 5, 6, 5, 6 };
+ int dbits = dbits_tab[modeval];
+
+ // extract six variable-placement bits
+ int bit0 = (v2 >> 6) & 1;
+ int bit1 = (v3 >> 6) & 1;
+ int bit2 = (v4 >> 6) & 1;
+ int bit3 = (v5 >> 6) & 1;
+ int bit4 = (v4 >> 5) & 1;
+ int bit5 = (v5 >> 5) & 1;
+
+ // and prepend the variable-placement bits depending on mode.
+ int ohmod = 1 << modeval; // one-hot-mode
+ if (ohmod & 0xA4)
+ a |= bit0 << 9;
+ if (ohmod & 0x8)
+ a |= bit2 << 9;
+ if (ohmod & 0x50)
+ a |= bit4 << 9;
+
+ if (ohmod & 0x50)
+ a |= bit5 << 10;
+ if (ohmod & 0xA0)
+ a |= bit1 << 10;
+
+ if (ohmod & 0xC0)
+ a |= bit2 << 11;
+
+ if (ohmod & 0x4)
+ c |= bit1 << 6;
+ if (ohmod & 0xE8)
+ c |= bit3 << 6;
+
+ if (ohmod & 0x20)
+ c |= bit2 << 7;
+
+ if (ohmod & 0x5B)
+ {
+ b0 |= bit0 << 6;
+ b1 |= bit1 << 6;
+ }
+
+ if (ohmod & 0x12)
+ {
+ b0 |= bit2 << 7;
+ b1 |= bit3 << 7;
+ }
+
+ if (ohmod & 0xAF)
+ {
+ d0 |= bit4 << 5;
+ d1 |= bit5 << 5;
+ }
+
+ if (ohmod & 0x5)
+ {
+ d0 |= bit2 << 6;
+ d1 |= bit3 << 6;
+ }
+
+ // sign-extend 'd0' and 'd1'
+ // note: this code assumes that signed right-shift actually sign-fills, not zero-fills.
+ int32_t d0x = d0;
+ int32_t d1x = d1;
+ int sx_shamt = 32 - dbits;
+ d0x <<= sx_shamt;
+ d0x >>= sx_shamt;
+ d1x <<= sx_shamt;
+ d1x >>= sx_shamt;
+ d0 = d0x;
+ d1 = d1x;
+
+ // expand all values to 12 bits, with left-shift as needed.
+ int val_shamt = (modeval >> 1) ^ 3;
+ a <<= val_shamt;
+ b0 <<= val_shamt;
+ b1 <<= val_shamt;
+ c <<= val_shamt;
+ d0 <<= val_shamt;
+ d1 <<= val_shamt;
+
+ // then compute the actual color values.
+ int red1 = a;
+ int green1 = a - b0;
+ int blue1 = a - b1;
+ int red0 = a - c;
+ int green0 = a - b0 - c - d0;
+ int blue0 = a - b1 - c - d1;
+
+ // clamp the color components to [0,2^12 - 1]
+ red0 = astc::clamp(red0, 0, 4095);
+ green0 = astc::clamp(green0, 0, 4095);
+ blue0 = astc::clamp(blue0, 0, 4095);
+
+ red1 = astc::clamp(red1, 0, 4095);
+ green1 = astc::clamp(green1, 0, 4095);
+ blue1 = astc::clamp(blue1, 0, 4095);
+
+ // switch around the color components
+ int temp0, temp1;
+ switch (majcomp)
+ {
+ case 1: // switch around red and green
+ temp0 = red0;
+ temp1 = red1;
+ red0 = green0;
+ red1 = green1;
+ green0 = temp0;
+ green1 = temp1;
+ break;
+ case 2: // switch around red and blue
+ temp0 = red0;
+ temp1 = red1;
+ red0 = blue0;
+ red1 = blue1;
+ blue0 = temp0;
+ blue1 = temp1;
+ break;
+ case 0: // no switch
+ break;
+ }
+
+ output0 = vint4(red0 << 4, green0 << 4, blue0 << 4, 0x7800);
+ output1 = vint4(red1 << 4, green1 << 4, blue1 << 4, 0x7800);
+}
+
+/**
+ * @brief Unpack an HDR RGB + LDR A direct encoding.
+ *
+ * @param input The packed endpoints (packed and modal).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void hdr_rgb_ldr_alpha_unpack(
+ const uint8_t input[8],
+ vint4& output0,
+ vint4& output1
+) {
+ hdr_rgb_unpack(input, output0, output1);
+
+ int v6 = input[6];
+ int v7 = input[7];
+ output0.set_lane<3>(v6);
+ output1.set_lane<3>(v7);
+}
+
+/**
+ * @brief Unpack an HDR L (small range) direct encoding.
+ *
+ * @param input The packed endpoints (packed and modal).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void hdr_luminance_small_range_unpack(
+ const uint8_t input[2],
+ vint4& output0,
+ vint4& output1
+) {
+ int v0 = input[0];
+ int v1 = input[1];
+
+ int y0, y1;
+ if (v0 & 0x80)
+ {
+ y0 = ((v1 & 0xE0) << 4) | ((v0 & 0x7F) << 2);
+ y1 = (v1 & 0x1F) << 2;
+ }
+ else
+ {
+ y0 = ((v1 & 0xF0) << 4) | ((v0 & 0x7F) << 1);
+ y1 = (v1 & 0xF) << 1;
+ }
+
+ y1 += y0;
+ if (y1 > 0xFFF)
+ {
+ y1 = 0xFFF;
+ }
+
+ output0 = vint4(y0 << 4, y0 << 4, y0 << 4, 0x7800);
+ output1 = vint4(y1 << 4, y1 << 4, y1 << 4, 0x7800);
+}
+
+/**
+ * @brief Unpack an HDR L (large range) direct encoding.
+ *
+ * @param input The packed endpoints (packed and modal).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void hdr_luminance_large_range_unpack(
+ const uint8_t input[2],
+ vint4& output0,
+ vint4& output1
+) {
+ int v0 = input[0];
+ int v1 = input[1];
+
+ int y0, y1;
+ if (v1 >= v0)
+ {
+ y0 = v0 << 4;
+ y1 = v1 << 4;
+ }
+ else
+ {
+ y0 = (v1 << 4) + 8;
+ y1 = (v0 << 4) - 8;
+ }
+
+ output0 = vint4(y0 << 4, y0 << 4, y0 << 4, 0x7800);
+ output1 = vint4(y1 << 4, y1 << 4, y1 << 4, 0x7800);
+}
+
+/**
+ * @brief Unpack an HDR A direct encoding.
+ *
+ * @param input The packed endpoints (packed and modal).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void hdr_alpha_unpack(
+ const uint8_t input[2],
+ int& output0,
+ int& output1
+) {
+
+ int v6 = input[0];
+ int v7 = input[1];
+
+ int selector = ((v6 >> 7) & 1) | ((v7 >> 6) & 2);
+ v6 &= 0x7F;
+ v7 &= 0x7F;
+ if (selector == 3)
+ {
+ output0 = v6 << 5;
+ output1 = v7 << 5;
+ }
+ else
+ {
+ v6 |= (v7 << (selector + 1)) & 0x780;
+ v7 &= (0x3f >> selector);
+ v7 ^= 32 >> selector;
+ v7 -= 32 >> selector;
+ v6 <<= (4 - selector);
+ v7 <<= (4 - selector);
+ v7 += v6;
+
+ if (v7 < 0)
+ {
+ v7 = 0;
+ }
+ else if (v7 > 0xFFF)
+ {
+ v7 = 0xFFF;
+ }
+
+ output0 = v6;
+ output1 = v7;
+ }
+
+ output0 <<= 4;
+ output1 <<= 4;
+}
+
+/**
+ * @brief Unpack an HDR RGBA direct encoding.
+ *
+ * @param input The packed endpoints (packed and modal).
+ * @param[out] output0 The unpacked endpoint 0 color.
+ * @param[out] output1 The unpacked endpoint 1 color.
+ */
+static void hdr_rgb_hdr_alpha_unpack(
+ const uint8_t input[8],
+ vint4& output0,
+ vint4& output1
+) {
+ hdr_rgb_unpack(input, output0, output1);
+
+ int alpha0, alpha1;
+ hdr_alpha_unpack(input + 6, alpha0, alpha1);
+
+ output0.set_lane<3>(alpha0);
+ output1.set_lane<3>(alpha1);
+}
+
+/* See header for documentation. */
+void unpack_color_endpoints(
+ astcenc_profile decode_mode,
+ int format,
+ const uint8_t* input,
+ bool& rgb_hdr,
+ bool& alpha_hdr,
+ vint4& output0,
+ vint4& output1
+) {
+ // Assume no NaNs and LDR endpoints unless set later
+ rgb_hdr = false;
+ alpha_hdr = false;
+
+ bool alpha_hdr_default = false;
+
+ switch (format)
+ {
+ case FMT_LUMINANCE:
+ luminance_unpack(input, output0, output1);
+ break;
+
+ case FMT_LUMINANCE_DELTA:
+ luminance_delta_unpack(input, output0, output1);
+ break;
+
+ case FMT_HDR_LUMINANCE_SMALL_RANGE:
+ rgb_hdr = true;
+ alpha_hdr_default = true;
+ hdr_luminance_small_range_unpack(input, output0, output1);
+ break;
+
+ case FMT_HDR_LUMINANCE_LARGE_RANGE:
+ rgb_hdr = true;
+ alpha_hdr_default = true;
+ hdr_luminance_large_range_unpack(input, output0, output1);
+ break;
+
+ case FMT_LUMINANCE_ALPHA:
+ luminance_alpha_unpack(input, output0, output1);
+ break;
+
+ case FMT_LUMINANCE_ALPHA_DELTA:
+ luminance_alpha_delta_unpack(input, output0, output1);
+ break;
+
+ case FMT_RGB_SCALE:
+ {
+ vint4 input0q(input[0], input[1], input[2], 0);
+ uint8_t scale = input[3];
+ rgb_scale_unpack(input0q, scale, output0, output1);
+ }
+ break;
+
+ case FMT_RGB_SCALE_ALPHA:
+ {
+ vint4 input0q(input[0], input[1], input[2], input[4]);
+ uint8_t alpha1q = input[5];
+ uint8_t scaleq = input[3];
+ rgb_scale_alpha_unpack(input0q, alpha1q, scaleq, output0, output1);
+ }
+ break;
+
+ case FMT_HDR_RGB_SCALE:
+ rgb_hdr = true;
+ alpha_hdr_default = true;
+ hdr_rgbo_unpack(input, output0, output1);
+ break;
+
+ case FMT_RGB:
+ {
+ vint4 input0q(input[0], input[2], input[4], 0);
+ vint4 input1q(input[1], input[3], input[5], 0);
+ rgb_unpack(input0q, input1q, output0, output1);
+ }
+ break;
+
+ case FMT_RGB_DELTA:
+ {
+ vint4 input0q(input[0], input[2], input[4], 0);
+ vint4 input1q(input[1], input[3], input[5], 0);
+ rgb_delta_unpack(input0q, input1q, output0, output1);
+ }
+ break;
+
+ case FMT_HDR_RGB:
+ rgb_hdr = true;
+ alpha_hdr_default = true;
+ hdr_rgb_unpack(input, output0, output1);
+ break;
+
+ case FMT_RGBA:
+ {
+ vint4 input0q(input[0], input[2], input[4], input[6]);
+ vint4 input1q(input[1], input[3], input[5], input[7]);
+ rgba_unpack(input0q, input1q, output0, output1);
+ }
+ break;
+
+ case FMT_RGBA_DELTA:
+ {
+ vint4 input0q(input[0], input[2], input[4], input[6]);
+ vint4 input1q(input[1], input[3], input[5], input[7]);
+ rgba_delta_unpack(input0q, input1q, output0, output1);
+ }
+ break;
+
+ case FMT_HDR_RGB_LDR_ALPHA:
+ rgb_hdr = true;
+ hdr_rgb_ldr_alpha_unpack(input, output0, output1);
+ break;
+
+ case FMT_HDR_RGBA:
+ rgb_hdr = true;
+ alpha_hdr = true;
+ hdr_rgb_hdr_alpha_unpack(input, output0, output1);
+ break;
+ }
+
+ // Assign a correct default alpha
+ if (alpha_hdr_default)
+ {
+ if (decode_mode == ASTCENC_PRF_HDR)
+ {
+ output0.set_lane<3>(0x7800);
+ output1.set_lane<3>(0x7800);
+ alpha_hdr = true;
+ }
+ else
+ {
+ output0.set_lane<3>(0x00FF);
+ output1.set_lane<3>(0x00FF);
+ alpha_hdr = false;
+ }
+ }
+
+ vint4 ldr_scale(257);
+ vint4 hdr_scale(1);
+ vint4 output_scale = ldr_scale;
+
+ // An LDR profile image
+ if ((decode_mode == ASTCENC_PRF_LDR) ||
+ (decode_mode == ASTCENC_PRF_LDR_SRGB))
+ {
+ // Also matches HDR alpha, as cannot have HDR alpha without HDR RGB
+ if (rgb_hdr == true)
+ {
+ output0 = vint4(0xFF00, 0x0000, 0xFF00, 0xFF00);
+ output1 = vint4(0xFF00, 0x0000, 0xFF00, 0xFF00);
+ output_scale = hdr_scale;
+
+ rgb_hdr = false;
+ alpha_hdr = false;
+ }
+ }
+ // An HDR profile image
+ else
+ {
+ vmask4 hdr_lanes(rgb_hdr, rgb_hdr, rgb_hdr, alpha_hdr);
+ output_scale = select(ldr_scale, hdr_scale, hdr_lanes);
+ }
+
+ output0 = output0 * output_scale;
+ output1 = output1 * output_scale;
+}