diff options
Diffstat (limited to 'thirdparty/astcenc/astcenc_color_quantize.cpp')
-rw-r--r-- | thirdparty/astcenc/astcenc_color_quantize.cpp | 142 |
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); } |