godot/thirdparty/astcenc/astcenc.h

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

/**
 * @brief The core astcenc codec library interface.
 *
 * This interface is the entry point to the core astcenc codec. It aims to be easy to use for
 * non-experts, but also to allow experts to have fine control over the compressor heuristics if
 * needed. The core codec only handles compression and decompression, transferring all inputs and
 * outputs via memory buffers. To catch obvious input/output buffer sizing issues, which can cause
 * security and stability problems, all transfer buffers are explicitly sized.
 *
 * While the aim is that we keep this interface mostly stable, it should be viewed as a mutable
 * interface tied to a specific source version. We are not trying to maintain backwards
 * compatibility across codec versions.
 *
 * The API state management is based around an explicit context object, which is the context for all
 * allocated memory resources needed to compress and decompress a single image. A context can be
 * used to sequentially compress multiple images using the same configuration, allowing setup
 * overheads to be amortized over multiple images, which is particularly important when images are
 * small.
 *
 * Multi-threading can be used two ways.
 *
 *     * An application wishing to process multiple images in parallel can allocate multiple
 *       contexts and assign each context to a thread.
 *     * An application wishing to process a single image in using multiple threads can configure
 *       contexts for multi-threaded use, and invoke astcenc_compress/decompress() once per thread
 *       for faster processing. The caller is responsible for creating the worker threads, and
 *       synchronizing between images.
 *
 * Extended instruction set support
 * ================================
 *
 * This library supports use of extended instruction sets, such as SSE4.1 and AVX2. These are
 * enabled at compile time when building the library. There is no runtime checking in the core
 * library that the instruction sets used are actually available. Checking compatibility is the
 * responsibility of the calling code.
 *
 * Threading
 * =========
 *
 * In pseudo-code, the usage for manual user threading looks like this:
 *
 *     // Configure the compressor run
 *     astcenc_config my_config;
 *     astcenc_config_init(..., &my_config);
 *
 *     // Power users can tweak <my_config> settings here ...
 *
 *     // Allocate working state given config and thread_count
 *     astcenc_context* my_context;
 *     astcenc_context_alloc(&my_config, thread_count, &my_context);
 *
 *     // Compress each image using these config settings
 *     foreach image:
 *         // For each thread in the thread pool
 *         for i in range(0, thread_count):
 *             astcenc_compress_image(my_context, &my_input, my_output, i);
 *
 *         astcenc_compress_reset(my_context);
 *
 *     // Clean up
 *     astcenc_context_free(my_context);
 *
 * Images
 * ======
 *
 * The codec supports compressing single images, which can be either 2D images or volumetric 3D
 * images. Calling code is responsible for any handling of aggregate types, such as mipmap chains,
 * texture arrays, or sliced 3D textures.
 *
 * Images are passed in as an astcenc_image structure. Inputs can be either 8-bit unorm, 16-bit
 * half-float, or 32-bit float, as indicated by the data_type field.
 *
 * Images can be any dimension; there is no requirement to be a multiple of the ASTC block size.
 *
 * Data is always passed in as 4 color components, and accessed as an array of 2D image slices. Data
 * within an image slice is always tightly packed without padding. Addressing looks like this:
 *
 *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4    ]   // Red
 *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4 + 1]   // Green
 *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4 + 2]   // Blue
 *     data[z_coord][y_coord * x_dim * 4 + x_coord * 4 + 3]   // Alpha
 *
 * Common compressor usage
 * =======================
 *
 * One of the most important things for coding image quality is to align the input data component
 * count with the ASTC color endpoint mode. This avoids wasting bits encoding components you don't
 * actually need in the endpoint colors.
 *
 *         | Input data   | Encoding swizzle | Sampling swizzle |
 *         | ------------ | ---------------- | ---------------- |
 *         | 1 component  | RRR1             | .[rgb]           |
 *         | 2 components | RRRG             | .[rgb]a          |
 *         | 3 components | RGB1             | .rgb             |
 *         | 4 components | RGBA             | .rgba            |
 *
 * The 1 and 2 component modes recommend sampling from "g" to recover the luminance value as this
 * provide best compatibility with other texture formats where the green component may be stored at
 * higher precision than the others, such as RGB565. For ASTC any of the RGB components can be used;
 * the luminance endpoint component will be returned for all three.
 *
 * When using the normal map compression mode ASTC will store normals as a two component X+Y map.
 * Input images must contain unit-length normalized and should be passed in using a two component
 * swizzle. The astcenc command line tool defaults to an RRRG swizzle, but some developers prefer
 * to use GGGR for compatability with BC5n which will work just as well. The Z component can be
 * recovered programmatically in shader code, using knowledge that the vector is unit length and
 * that Z must be positive for a tangent-space normal map.
 *
 * Decompress-only usage
 * =====================
 *
 * For some use cases it is useful to have a cut-down context and/or library which supports
 * decompression but not compression.
 *
 * A context can be made decompress-only using the ASTCENC_FLG_DECOMPRESS_ONLY flag when the context
 * is allocated. These contexts have lower dynamic memory footprint than a full context.
 *
 * The entire library can be made decompress-only by building the files with the define
 * ASTCENC_DECOMPRESS_ONLY set. In this build the context will be smaller, and the library will
 * exclude the functionality which is only needed for compression. This reduces the binary size by
 * ~180KB. For these builds contexts must be created with the ASTCENC_FLG_DECOMPRESS_ONLY flag.
 *
 * Note that context structures returned by a library built as decompress-only are incompatible with
 * a library built with compression included, and visa versa, as they have different sizes and
 * memory layout.
 *
 * Self-decompress-only usage
 * ==========================
 *
 * ASTC is a complex format with a large search space. The parts of this search space that are
 * searched is determined by heuristics that are, in part, tied to the quality level used when
 * creating the context.
 *
 * A normal context is capable of decompressing any ASTC texture, including those generated by other
 * compressors with unknown heuristics. This is the most flexible implementation, but forces the
 * data tables used by the codec to include entries that are not needed during compression. This
 * can slow down context creation by a significant amount, especially for the faster compression
 * modes where few data table entries are actually used. To optimize this use case the context can
 * be created with the ASTCENC_FLG_SELF_DECOMPRESS_ONLY flag. This tells the compressor that it will
 * only be asked to decompress images that it compressed itself, allowing the data tables to
 * exclude entries that are not needed by the current compression configuration. This reduces the
 * size of the context data tables in memory and improves context creation performance. Note that,
 * as of the 3.6 release, this flag no longer affects compression performance.
 *
 * Using this flag while attempting to decompress an valid image which was created by another
 * compressor, or even another astcenc compressor version or configuration, may result in blocks
 * returning as solid magenta or NaN value error blocks.
 */

#ifndef ASTCENC_INCLUDED
#define ASTCENC_INCLUDED

#include <cstddef>
#include <cstdint>

#if defined(ASTCENC_DYNAMIC_LIBRARY)
	#if defined(_MSC_VER)
		#define ASTCENC_PUBLIC
	#else
		#define ASTCENC_PUBLIC
	#endif
#else
	#define ASTCENC_PUBLIC
#endif

/* ============================================================================
    Data declarations
============================================================================ */

/**
 * @brief An opaque structure; see astcenc_internal.h for definition.
 */
struct astcenc_context;

/**
 * @brief A codec API error code.
 */
enum astcenc_error {};

/**
 * @brief A codec color profile.
 */
enum astcenc_profile {};

/** @brief The fastest, lowest quality, search preset. */
static const float ASTCENC_PRE_FASTEST =;

/** @brief The fast search preset. */
static const float ASTCENC_PRE_FAST =;

/** @brief The medium quality search preset. */
static const float ASTCENC_PRE_MEDIUM =;

/** @brief The thorough quality search preset. */
static const float ASTCENC_PRE_THOROUGH =;

/** @brief The thorough quality search preset. */
static const float ASTCENC_PRE_VERYTHOROUGH =;

/** @brief The exhaustive, highest quality, search preset. */
static const float ASTCENC_PRE_EXHAUSTIVE =;

/**
 * @brief A codec component swizzle selector.
 */
enum astcenc_swz
{};

/**
 * @brief A texel component swizzle.
 */
struct astcenc_swizzle
{};

/**
 * @brief A texel component data format.
 */
enum astcenc_type
{};

/**
 * @brief Function pointer type for compression progress reporting callback.
 */
extern "C" astcenc_progress_callback;

/**
 * @brief Enable normal map compression.
 *
 * Input data will be treated a two component normal map, storing X and Y, and the codec will
 * optimize for angular error rather than simple linear PSNR. In this mode the input swizzle should
 * be e.g. rrrg (the default ordering for ASTC normals on the command line) or gggr (the ordering
 * used by BC5n).
 */
static const unsigned int ASTCENC_FLG_MAP_NORMAL          =;

/**
 * @brief Enable compression heuristics that assume use of decode_unorm8 decode mode.
 *
 * The decode_unorm8 decode mode rounds differently to the decode_fp16 decode mode, so enabling this
 * flag during compression will allow the compressor to use the correct rounding when selecting
 * encodings. This will improve the compressed image quality if your application is using the
 * decode_unorm8 decode mode, but will reduce image quality if using decode_fp16.
 *
 * Note that LDR_SRGB images will always use decode_unorm8 for the RGB channels, irrespective of
 * this setting.
 */
static const unsigned int ASTCENC_FLG_USE_DECODE_UNORM8        =;

/**
 * @brief Enable alpha weighting.
 *
 * The input alpha value is used for transparency, so errors in the RGB components are weighted by
 * the transparency level. This allows the codec to more accurately encode the alpha value in areas
 * where the color value is less significant.
 */
static const unsigned int ASTCENC_FLG_USE_ALPHA_WEIGHT     =;

/**
 * @brief Enable perceptual error metrics.
 *
 * This mode enables perceptual compression mode, which will optimize for perceptual error rather
 * than best PSNR. Only some input modes support perceptual error metrics.
 */
static const unsigned int ASTCENC_FLG_USE_PERCEPTUAL       =;

/**
 * @brief Create a decompression-only context.
 *
 * This mode disables support for compression. This enables context allocation to skip some
 * transient buffer allocation, resulting in lower memory usage.
 */
static const unsigned int ASTCENC_FLG_DECOMPRESS_ONLY      =;

/**
 * @brief Create a self-decompression context.
 *
 * This mode configures the compressor so that it is only guaranteed to be able to decompress images
 * that were actually created using the current context. This is the common case for compression use
 * cases, and setting this flag enables additional optimizations, but does mean that the context
 * cannot reliably decompress arbitrary ASTC images.
 */
static const unsigned int ASTCENC_FLG_SELF_DECOMPRESS_ONLY =;

/**
 * @brief Enable RGBM map compression.
 *
 * Input data will be treated as HDR data that has been stored in an LDR RGBM-encoded wrapper
 * format. Data must be preprocessed by the user to be in LDR RGBM format before calling the
 * compression function, this flag is only used to control the use of RGBM-specific heuristics and
 * error metrics.
 *
 * IMPORTANT: The ASTC format is prone to bad failure modes with unconstrained RGBM data; very small
 * M values can round to zero due to quantization and result in black or white pixels. It is highly
 * recommended that the minimum value of M used in the encoding is kept above a lower threshold (try
 * 16 or 32). Applying this threshold reduces the number of very dark colors that can be
 * represented, but is still higher precision than 8-bit LDR.
 *
 * When this flag is set the value of @c rgbm_m_scale in the context must be set to the RGBM scale
 * factor used during reconstruction. This defaults to 5 when in RGBM mode.
 *
 * It is recommended that the value of @c cw_a_weight is set to twice the value of the multiplier
 * scale, ensuring that the M value is accurately encoded. This defaults to 10 when in RGBM mode,
 * matching the default scale factor.
 */
static const unsigned int ASTCENC_FLG_MAP_RGBM             =;

/**
 * @brief The bit mask of all valid flags.
 */
static const unsigned int ASTCENC_ALL_FLAGS =;

/**
 * @brief The config structure.
 *
 * This structure will initially be populated by a call to astcenc_config_init, but power users may
 * modify it before calling astcenc_context_alloc. See astcenccli_toplevel_help.cpp for full user
 * documentation of the power-user settings.
 *
 * Note for any settings which are associated with a specific color component, the value in the
 * config applies to the component that exists after any compression data swizzle is applied.
 */
struct astcenc_config
{};

/**
 * @brief An uncompressed 2D or 3D image.
 *
 * 3D image are passed in as an array of 2D slices. Each slice has identical
 * size and color format.
 */
struct astcenc_image
{};

/**
 * @brief A block encoding metadata query result.
 *
 * If the block is an error block or a constant color block or an error block all fields other than
 * the profile, block dimensions, and error/constant indicator will be zero.
 */
struct astcenc_block_info
{};

/**
 * Populate a codec config based on default settings.
 *
 * Power users can edit the returned config struct to fine tune before allocating the context.
 *
 * @param      profile   Color profile.
 * @param      block_x   ASTC block size X dimension.
 * @param      block_y   ASTC block size Y dimension.
 * @param      block_z   ASTC block size Z dimension.
 * @param      quality   Search quality preset / effort level. Either an
 *                       @c ASTCENC_PRE_* value, or a effort level between 0
 *                       and 100. Performance is not linear between 0 and 100.

 * @param      flags     A valid set of @c ASTCENC_FLG_* flag bits.
 * @param[out] config    Output config struct to populate.
 *
 * @return @c ASTCENC_SUCCESS on success, or an error if the inputs are invalid
 * either individually, or in combination.
 */
ASTCENC_PUBLIC astcenc_error astcenc_config_init(
	astcenc_profile profile,
	unsigned int block_x,
	unsigned int block_y,
	unsigned int block_z,
	float quality,
	unsigned int flags,
	astcenc_config* config);

/**
 * @brief Allocate a new codec context based on a config.
 *
 * This function allocates all of the memory resources and threads needed by the codec. This can be
 * slow, so it is recommended that contexts are reused to serially compress or decompress multiple
 * images to amortize setup cost.
 *
 * Contexts can be allocated to support only decompression using the @c ASTCENC_FLG_DECOMPRESS_ONLY
 * flag when creating the configuration. The compression functions will fail if invoked. For a
 * decompress-only library build the @c ASTCENC_FLG_DECOMPRESS_ONLY flag must be set when creating
 * any context.
 *
 * @param[in]  config         Codec config.
 * @param      thread_count   Thread count to configure for.
 * @param[out] context        Location to store an opaque context pointer.
 *
 * @return @c ASTCENC_SUCCESS on success, or an error if context creation failed.
 */
ASTCENC_PUBLIC astcenc_error astcenc_context_alloc(
	const astcenc_config* config,
	unsigned int thread_count,
	astcenc_context** context);

/**
 * @brief Compress an image.
 *
 * A single context can only compress or decompress a single image at a time.
 *
 * For a context configured for multi-threading, any set of the N threads can call this function.
 * Work will be dynamically scheduled across the threads available. Each thread must have a unique
 * @c thread_index.
 *
 * @param         context        Codec context.
 * @param[in,out] image          An input image, in 2D slices.
 * @param         swizzle        Compression data swizzle, applied before compression.
 * @param[out]    data_out       Pointer to output data array.
 * @param         data_len       Length of the output data array.
 * @param         thread_index   Thread index [0..N-1] of calling thread.
 *
 * @return @c ASTCENC_SUCCESS on success, or an error if compression failed.
 */
ASTCENC_PUBLIC astcenc_error astcenc_compress_image(
	astcenc_context* context,
	astcenc_image* image,
	const astcenc_swizzle* swizzle,
	uint8_t* data_out,
	size_t data_len,
	unsigned int thread_index);

/**
 * @brief Reset the codec state for a new compression.
 *
 * The caller is responsible for synchronizing threads in the worker thread pool. This function must
 * only be called when all threads have exited the @c astcenc_compress_image() function for image N,
 * but before any thread enters it for image N + 1.
 *
 * Calling this is not required (but won't hurt), if the context is created for single threaded use.
 *
 * @param context   Codec context.
 *
 * @return @c ASTCENC_SUCCESS on success, or an error if reset failed.
 */
ASTCENC_PUBLIC astcenc_error astcenc_compress_reset(
	astcenc_context* context);

/**
 * @brief Decompress an image.
 *
 * @param         context        Codec context.
 * @param[in]     data           Pointer to compressed data.
 * @param         data_len       Length of the compressed data, in bytes.
 * @param[in,out] image_out      Output image.
 * @param         swizzle        Decompression data swizzle, applied after decompression.
 * @param         thread_index   Thread index [0..N-1] of calling thread.
 *
 * @return @c ASTCENC_SUCCESS on success, or an error if decompression failed.
 */
ASTCENC_PUBLIC astcenc_error astcenc_decompress_image(
	astcenc_context* context,
	const uint8_t* data,
	size_t data_len,
	astcenc_image* image_out,
	const astcenc_swizzle* swizzle,
	unsigned int thread_index);

/**
 * @brief Reset the codec state for a new decompression.
 *
 * The caller is responsible for synchronizing threads in the worker thread pool. This function must
 * only be called when all threads have exited the @c astcenc_decompress_image() function for image
 * N, but before any thread enters it for image N + 1.
 *
 * Calling this is not required (but won't hurt), if the context is created for single threaded use.
 *
 * @param context   Codec context.
 *
 * @return @c ASTCENC_SUCCESS on success, or an error if reset failed.
 */
ASTCENC_PUBLIC astcenc_error astcenc_decompress_reset(
	astcenc_context* context);

/**
 * Free the compressor context.
 *
 * @param context   The codec context.
 */
ASTCENC_PUBLIC void astcenc_context_free(
	astcenc_context* context);

/**
 * @brief Provide a high level summary of a block's encoding.
 *
 * This feature is primarily useful for codec developers but may be useful for developers building
 * advanced content packaging pipelines.
 *
 * @param context   Codec context.
 * @param data      One block of compressed ASTC data.
 * @param info      The output info structure to populate.
 *
 * @return @c ASTCENC_SUCCESS if the block was decoded, or an error otherwise. Note that this
 *         function will return success even if the block itself was an error block encoding, as the
 *         decode was correctly handled.
 */
ASTCENC_PUBLIC astcenc_error astcenc_get_block_info(
	astcenc_context* context,
	const uint8_t data[16],
	astcenc_block_info* info);

/**
 * @brief Get a printable string for specific status code.
 *
 * @param status   The status value.
 *
 * @return A human readable nul-terminated string.
 */
ASTCENC_PUBLIC const char* astcenc_get_error_string(
	astcenc_error status);

#endif