godot/thirdparty/astcenc/astcenc_color_quantize.cpp

// SPDX-License-Identifier: Apache-2.0
// ----------------------------------------------------------------------------
// 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
// 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.
// ----------------------------------------------------------------------------

#if !defined(ASTCENC_DECOMPRESS_ONLY)

/**
 * @brief Functions for color quantization.
 *
 * The design of the color quantization functionality requires the caller to use higher level error
 * analysis to determine the base encoding that should be used. This earlier analysis will select
 * the basic type of the endpoint that should be used:
 *
 *     * Mode: LDR or HDR
 *     * Quantization level
 *     * Channel count: L, LA, RGB, or RGBA
 *     * Endpoint 2 type: Direct color endcode, or scaled from endpoint 1.
 *
 * However, this leaves a number of decisions about exactly how to pack the endpoints open. In
 * particular we need to determine if blue contraction can be used, or/and if delta encoding can be
 * used. If they can be applied these will allow us to maintain higher precision in the endpoints
 * without needing additional storage.
 */

#include <stdio.h>
#include <assert.h>

#include "astcenc_internal.h"

/**
 * @brief Compute the error of an LDR RGB or RGBA encoding.
 *
 * @param uquant0    The original endpoint 0 color.
 * @param uquant1    The original endpoint 1 color.
 * @param quant0     The unpacked quantized endpoint 0 color.
 * @param quant1     The unpacked quantized endpoint 1 color.
 *
 * @return The MSE of the encoding.
 */
static float get_rgba_encoding_error(
	vfloat4 uquant0,
	vfloat4 uquant1,
	vint4 quant0,
	vint4 quant1
) {}

/**
 * @brief Determine the quantized value given a quantization level.
 *
 * @param quant_level   The quantization level to use.
 * @param value         The value to convert. This must be in the 0-255 range.
 *
 * @return The unpacked quantized value, returned in 0-255 range.
 */
static inline uint8_t quant_color(
	quant_method quant_level,
	int value
) {}

/**
 * @brief Determine the quantized value given a quantization level.
 *
 * @param quant_level   The quantization level to use.
 * @param value         The value to convert. This must be in the 0-255 range.
 *
 * @return The unpacked quantized value, returned in 0-255 range.
 */
static inline vint4 quant_color3(
	quant_method quant_level,
	vint4 value
) {}

/**
 * @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
) {}

/**
 * @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 vint4 quant_color3(
	quant_method quant_level,
	vint4 value,
	vfloat4 valuef
) {}

/**
 * @brief Quantize an LDR RGB color.
 *
 * Since this is a fall-back encoding, we cannot actually fail but must produce a sensible result.
 * For this encoding @c color0 cannot be larger than @c color1. If @c color0 is actually larger
 * than @c color1, @c color0 is reduced and @c color1 is increased until the constraint is met.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out    The output quantized color0 endpoint.
 * @param[out] color1_out    The output quantized color1 endpoint.
 * @param      quant_level   The quantization level to use.
 */
static void quantize_rgb(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Quantize an LDR RGBA color.
 *
 * Since this is a fall-back encoding, we cannot actually fail but must produce a sensible result.
 * For this encoding @c color0.rgb cannot be larger than @c color1.rgb (this indicates blue
 * contraction). If @c color0.rgb is actually larger than @c color1.rgb, @c color0.rgb is reduced
 * and @c color1.rgb is increased until the constraint is met.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out    The output quantized color0 endpoint.
 * @param[out] color1_out    The output quantized color1 endpoint.
 * @param      quant_level   The quantization level to use.
 */
static void quantize_rgba(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR RGB color using blue-contraction.
 *
 * Blue-contraction is only usable if encoded color 1 is larger than color 0.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out    The output quantized color0 endpoint.
 * @param[out] color1_out    The output quantized color1 endpoint.
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_rgb_blue_contract(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR RGBA color using blue-contraction.
 *
 * Blue-contraction is only usable if encoded color 1 RGB is larger than color 0 RGB.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out    The output quantized color0 endpoint.
 * @param[out] color1_out    The output quantized color1 endpoint.
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_rgba_blue_contract(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR RGB color using delta encoding.
 *
 * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
 * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
 * non-negative, then we encode a regular delta.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out    The output quantized color0 endpoint.
 * @param[out] color1_out    The output quantized color1 endpoint.
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_rgb_delta(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR RGB color using delta encoding and blue-contraction.
 *
 * Blue-contraction is only usable if encoded color 1 RGB is larger than color 0 RGB.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out    The output quantized color0 endpoint.
 * @param[out] color1_out    The output quantized color1 endpoint.
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_rgb_delta_blue_contract(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR A color using delta encoding.
 *
 * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
 * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
 * non-negative, then we encode a regular delta.
 *
 * This function only compressed the alpha - the other elements in the output array are not touched.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out    The output quantized color0 endpoint; must preserve lane 0/1/2.
 * @param[out] color1_out    The output quantized color1 endpoint; must preserve lane 0/1/2.
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_alpha_delta(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR LA color using delta encoding.
 *
 * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
 * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
 * non-negative, then we encode a regular delta.
 *
 * This function only compressed the alpha - the other elements in the output array are not touched.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as (l0, l1, a0, a1).
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_luminance_alpha_delta(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[4],
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR RGBA color using delta encoding.
 *
 * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
 * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
 * non-negative, then we encode a regular delta.
 *
 * This function only compressed the alpha - the other elements in the output array are not touched.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] color0_out   The output quantized color0 endpoint
 * @param[out] color1_out   The output quantized color1 endpoint
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_rgba_delta(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Try to quantize an LDR RGBA color using delta and blue contract encoding.
 *
 * At decode time we move one bit from the offset to the base and seize another bit as a sign bit;
 * we then unquantize both values as if they contain one extra bit. If the sum of the offsets is
 * non-negative, then we encode a regular delta.
 *
 * This function only compressed the alpha - the other elements in the output array are not touched.
 *
 * @param      color0       The input unquantized color0 endpoint.
 * @param      color1       The input unquantized color1 endpoint.
 * @param[out] color0_out   The output quantized color0 endpoint
 * @param[out] color1_out   The output quantized color1 endpoint
 * @param      quant_level  The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_rgba_delta_blue_contract(
	vfloat4 color0,
	vfloat4 color1,
	vint4& color0_out,
	vint4& color1_out,
	quant_method quant_level
) {}

/**
 * @brief Quantize an LDR RGB color using scale encoding.
 *
 * @param      color         The input unquantized color endpoint and scale factor.
 * @param[out] output        The output endpoints, returned as (r0, g0, b0, s).
 * @param      quant_level   The quantization level to use.
 */
static void quantize_rgbs(
	vfloat4 color,
	uint8_t output[4],
	quant_method quant_level
) {}

/**
 * @brief Quantize an LDR RGBA color using scale encoding.
 *
 * @param      color0       The input unquantized color0 alpha endpoint.
 * @param      color1       The input unquantized color1 alpha endpoint.
 * @param      color        The input unquantized color endpoint and scale factor.
 * @param[out] output       The output endpoints, returned as (r0, g0, b0, s, a0, a1).
 * @param      quant_level  The quantization level to use.
 */
static void quantize_rgbs_alpha(
	vfloat4 color0,
	vfloat4 color1,
	vfloat4 color,
	uint8_t output[6],
	quant_method quant_level
) {}

/**
 * @brief Quantize a LDR L color.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as (l0, l1).
 * @param      quant_level   The quantization level to use.
 */
static void quantize_luminance(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[2],
	quant_method quant_level
) {}

/**
 * @brief Quantize a LDR LA color.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as (l0, l1, a0, a1).
 * @param      quant_level   The quantization level to use.
 */
static void quantize_luminance_alpha(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[4],
	quant_method quant_level
) {}

/**
 * @brief Quantize and unquantize a value ensuring top two bits are the same.
 *
 * @param      quant_level     The quantization level to use.
 * @param      value           The input unquantized value.
 * @param[out] quant_value     The quantized value.
 */
static inline void quantize_and_unquantize_retain_top_two_bits(
	quant_method quant_level,
	uint8_t value,
	uint8_t& quant_value
) {}

/**
 * @brief Quantize and unquantize a value ensuring top four bits are the same.
 *
 * @param      quant_level     The quantization level to use.
 * @param      value           The input unquantized value.
 * @param[out] quant_value     The quantized value in 0-255 range.
 */
static inline void quantize_and_unquantize_retain_top_four_bits(
	quant_method quant_level,
	uint8_t value,
	uint8_t& quant_value
) {}

/**
 * @brief Quantize a HDR RGB color using RGB + offset.
 *
 * @param      color         The input unquantized color endpoint and offset.
 * @param[out] output        The output endpoints, returned as packed RGBS with some mode bits.
 * @param      quant_level   The quantization level to use.
 */
static void quantize_hdr_rgbo(
	vfloat4 color,
	uint8_t output[4],
	quant_method quant_level
) {}

/**
 * @brief Quantize a HDR RGB color using direct RGB encoding.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as packed RGB+RGB pairs with mode bits.
 * @param      quant_level   The quantization level to use.
 */
static void quantize_hdr_rgb(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[6],
	quant_method quant_level
) {}

/**
 * @brief Quantize a HDR RGB + LDR A color using direct RGBA encoding.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as packed RGBA+RGBA pairs with mode bits.
 * @param      quant_level   The quantization level to use.
 */
static void quantize_hdr_rgb_ldr_alpha(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[8],
	quant_method quant_level
) {}

/**
 * @brief Quantize a HDR L color using the large range encoding.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as packed (l0, l1).
 * @param      quant_level   The quantization level to use.
 */
static void quantize_hdr_luminance_large_range(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[2],
	quant_method quant_level
) {}

/**
 * @brief Quantize a HDR L color using the small range encoding.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as packed (l0, l1) with mode bits.
 * @param      quant_level   The quantization level to use.
 *
 * @return Returns @c false on failure, @c true on success.
 */
static bool try_quantize_hdr_luminance_small_range(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[2],
	quant_method quant_level
) {}

/**
 * @brief Quantize a HDR A color using either delta or direct RGBA encoding.
 *
 * @param      alpha0        The input unquantized color0 endpoint.
 * @param      alpha1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as packed RGBA+RGBA pairs with mode bits.
 * @param      quant_level   The quantization level to use.
 */
static void quantize_hdr_alpha(
	float alpha0,
	float alpha1,
	uint8_t output[2],
	quant_method quant_level
) {}

/**
 * @brief Quantize a HDR RGBA color using either delta or direct RGBA encoding.
 *
 * @param      color0        The input unquantized color0 endpoint.
 * @param      color1        The input unquantized color1 endpoint.
 * @param[out] output        The output endpoints, returned as packed RGBA+RGBA pairs with mode bits.
 * @param      quant_level   The quantization level to use.
 */
static void quantize_hdr_rgb_alpha(
	vfloat4 color0,
	vfloat4 color1,
	uint8_t output[8],
	quant_method quant_level
) {}

/* See header for documentation. */
uint8_t pack_color_endpoints(
	vfloat4 color0,
	vfloat4 color1,
	vfloat4 rgbs_color,
	vfloat4 rgbo_color,
	int format,
	uint8_t* output,
	quant_method quant_level
) {}

#endif