summaryrefslogtreecommitdiffstats
path: root/thirdparty/astcenc/astcenc_color_quantize.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/astcenc/astcenc_color_quantize.cpp')
-rw-r--r--thirdparty/astcenc/astcenc_color_quantize.cpp142
1 files changed, 65 insertions, 77 deletions
diff --git a/thirdparty/astcenc/astcenc_color_quantize.cpp b/thirdparty/astcenc/astcenc_color_quantize.cpp
index edcfe4f853..b0fec7a74c 100644
--- a/thirdparty/astcenc/astcenc_color_quantize.cpp
+++ b/thirdparty/astcenc/astcenc_color_quantize.cpp
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
-// Copyright 2011-2021 Arm Limited
+// Copyright 2011-2023 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
@@ -44,17 +44,43 @@
* @brief Determine the quantized value given a quantization level.
*
* @param quant_level The quantization level to use.
- * @param value The value to convert. This may be outside of the 0-255 range and will be
- * clamped before the value is looked up.
+ * @param value The value to convert. This must be in the 0-255 range.
*
- * @return The encoded quantized value. These are not necessarily in order; the compressor
- * scrambles the values slightly to make hardware implementation easier.
+ * @return The unpacked quantized value, returned in 0-255 range.
*/
static inline uint8_t quant_color(
quant_method quant_level,
int value
) {
- return color_unquant_to_uquant_tables[quant_level - QUANT_6][value];
+ int index = value * 2 + 1;
+ return color_unquant_to_uquant_tables[quant_level - QUANT_6][index];
+}
+
+/**
+ * @brief Determine the quantized value given a quantization level and residual.
+ *
+ * @param quant_level The quantization level to use.
+ * @param value The value to convert. This must be in the 0-255 range.
+ * @param valuef The original value before rounding, used to compute a residual.
+ *
+ * @return The unpacked quantized value, returned in 0-255 range.
+ */
+static inline uint8_t quant_color(
+ quant_method quant_level,
+ int value,
+ float valuef
+) {
+ int index = value * 2;
+
+ // Compute the residual to determine if we should round down or up ties.
+ // Test should be residual >= 0, but empirical testing shows small bias helps.
+ float residual = valuef - static_cast<float>(value);
+ if (residual >= -0.1f)
+ {
+ index++;
+ }
+
+ return color_unquant_to_uquant_tables[quant_level - QUANT_6][index];
}
/**
@@ -86,16 +112,16 @@ static void quantize_rgb(
float b1 = astc::clamp255f(color1.lane<2>() * scale);
int ri0, gi0, bi0, ri1, gi1, bi1;
- float rgb0_addon = 0.5f;
- float rgb1_addon = 0.5f;
+ float rgb0_addon = 0.0f;
+ float rgb1_addon = 0.0f;
do
{
- ri0 = quant_color(quant_level, astc::max(astc::flt2int_rd(r0 + rgb0_addon), 0));
- gi0 = quant_color(quant_level, astc::max(astc::flt2int_rd(g0 + rgb0_addon), 0));
- bi0 = quant_color(quant_level, astc::max(astc::flt2int_rd(b0 + rgb0_addon), 0));
- ri1 = quant_color(quant_level, astc::min(astc::flt2int_rd(r1 + rgb1_addon), 255));
- gi1 = quant_color(quant_level, astc::min(astc::flt2int_rd(g1 + rgb1_addon), 255));
- bi1 = quant_color(quant_level, astc::min(astc::flt2int_rd(b1 + rgb1_addon), 255));
+ ri0 = quant_color(quant_level, astc::max(astc::flt2int_rtn(r0 + rgb0_addon), 0), r0 + rgb0_addon);
+ gi0 = quant_color(quant_level, astc::max(astc::flt2int_rtn(g0 + rgb0_addon), 0), g0 + rgb0_addon);
+ bi0 = quant_color(quant_level, astc::max(astc::flt2int_rtn(b0 + rgb0_addon), 0), b0 + rgb0_addon);
+ ri1 = quant_color(quant_level, astc::min(astc::flt2int_rtn(r1 + rgb1_addon), 255), r1 + rgb1_addon);
+ gi1 = quant_color(quant_level, astc::min(astc::flt2int_rtn(g1 + rgb1_addon), 255), g1 + rgb1_addon);
+ bi1 = quant_color(quant_level, astc::min(astc::flt2int_rtn(b1 + rgb1_addon), 255), b1 + rgb1_addon);
rgb0_addon -= 0.2f;
rgb1_addon += 0.2f;
@@ -133,8 +159,8 @@ static void quantize_rgba(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[6] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[7] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[6] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[7] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
quantize_rgb(color0, color1, output, quant_level);
}
@@ -180,13 +206,13 @@ static bool try_quantize_rgb_blue_contract(
}
// Quantize the inverse-blue-contracted color
- int ri0 = quant_color(quant_level, astc::flt2int_rtn(r0));
- int gi0 = quant_color(quant_level, astc::flt2int_rtn(g0));
- int bi0 = quant_color(quant_level, astc::flt2int_rtn(b0));
+ int ri0 = quant_color(quant_level, astc::flt2int_rtn(r0), r0);
+ int gi0 = quant_color(quant_level, astc::flt2int_rtn(g0), g0);
+ int bi0 = quant_color(quant_level, astc::flt2int_rtn(b0), b0);
- int ri1 = quant_color(quant_level, astc::flt2int_rtn(r1));
- int gi1 = quant_color(quant_level, astc::flt2int_rtn(g1));
- int bi1 = quant_color(quant_level, astc::flt2int_rtn(b1));
+ int ri1 = quant_color(quant_level, astc::flt2int_rtn(r1), r1);
+ int gi1 = quant_color(quant_level, astc::flt2int_rtn(g1), g1);
+ int bi1 = quant_color(quant_level, astc::flt2int_rtn(b1), b1);
// If color #1 is not larger than color #0 then blue-contraction cannot be used. Note that
// blue-contraction and quantization change this order, which is why we must test afterwards.
@@ -217,7 +243,7 @@ static bool try_quantize_rgb_blue_contract(
*
* @return Returns @c false on failure, @c true on success.
*/
-static int try_quantize_rgba_blue_contract(
+static bool try_quantize_rgba_blue_contract(
vfloat4 color0,
vfloat4 color1,
uint8_t output[8],
@@ -228,8 +254,8 @@ static int try_quantize_rgba_blue_contract(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[6] = quant_color(quant_level, astc::flt2int_rtn(a1));
- output[7] = quant_color(quant_level, astc::flt2int_rtn(a0));
+ output[6] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
+ output[7] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
return try_quantize_rgb_blue_contract(color0, color1, output, quant_level);
}
@@ -433,7 +459,7 @@ static bool try_quantize_rgb_delta_blue_contract(
g1d |= (g0b & 0x100) >> 1;
b1d |= (b0b & 0x100) >> 1;
- // Then quantize and unquantize; if this causes any of the top two bits to flip,
+ // Then quantize and unquantize; if this causes any of the top two bits to flip,
// then encoding fails, since we have then corrupted either the top bit of the base
// or the sign bit of the offset.
int r1de = quant_color(quant_level, r1d);
@@ -728,9 +754,9 @@ static void quantize_rgbs(
float g = astc::clamp255f(color.lane<1>() * scale);
float b = astc::clamp255f(color.lane<2>() * scale);
- int ri = quant_color(quant_level, astc::flt2int_rtn(r));
- int gi = quant_color(quant_level, astc::flt2int_rtn(g));
- int bi = quant_color(quant_level, astc::flt2int_rtn(b));
+ int ri = quant_color(quant_level, astc::flt2int_rtn(r), r);
+ int gi = quant_color(quant_level, astc::flt2int_rtn(g), g);
+ int bi = quant_color(quant_level, astc::flt2int_rtn(b), b);
float oldcolorsum = hadd_rgb_s(color) * scale;
float newcolorsum = static_cast<float>(ri + gi + bi);
@@ -764,8 +790,8 @@ static void quantize_rgbs_alpha(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[4] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[5] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[4] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[5] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
quantize_rgbs(color, output, quant_level);
}
@@ -799,8 +825,8 @@ static void quantize_luminance(
lum1 = avg;
}
- output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0));
- output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1));
+ output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0), lum0);
+ output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1), lum1);
}
/**
@@ -828,48 +854,10 @@ static void quantize_luminance_alpha(
float a0 = astc::clamp255f(color0.lane<3>());
float a1 = astc::clamp255f(color1.lane<3>());
- // If endpoints are close then pull apart slightly; this gives > 8 bit normal map precision.
- if (quant_level > 18)
- {
- if (fabsf(lum0 - lum1) < 3.0f)
- {
- if (lum0 < lum1)
- {
- lum0 -= 0.5f;
- lum1 += 0.5f;
- }
- else
- {
- lum0 += 0.5f;
- lum1 -= 0.5f;
- }
-
- lum0 = astc::clamp255f(lum0);
- lum1 = astc::clamp255f(lum1);
- }
-
- if (fabsf(a0 - a1) < 3.0f)
- {
- if (a0 < a1)
- {
- a0 -= 0.5f;
- a1 += 0.5f;
- }
- else
- {
- a0 += 0.5f;
- a1 -= 0.5f;
- }
-
- a0 = astc::clamp255f(a0);
- a1 = astc::clamp255f(a1);
- }
- }
-
- output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0));
- output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1));
- output[2] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[3] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[0] = quant_color(quant_level, astc::flt2int_rtn(lum0), lum0);
+ output[1] = quant_color(quant_level, astc::flt2int_rtn(lum1), lum1);
+ output[2] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[3] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
}
/**
@@ -1661,8 +1649,8 @@ static void quantize_hdr_rgb_ldr_alpha(
float a0 = astc::clamp255f(color0.lane<3>() * scale);
float a1 = astc::clamp255f(color1.lane<3>() * scale);
- output[6] = quant_color(quant_level, astc::flt2int_rtn(a0));
- output[7] = quant_color(quant_level, astc::flt2int_rtn(a1));
+ output[6] = quant_color(quant_level, astc::flt2int_rtn(a0), a0);
+ output[7] = quant_color(quant_level, astc::flt2int_rtn(a1), a1);
quantize_hdr_rgb(color0, color1, output, quant_level);
}