340 lines
9.6 KiB
C++
340 lines
9.6 KiB
C++
// SPDX-License-Identifier: Apache-2.0
|
|
// ----------------------------------------------------------------------------
|
|
// Copyright 2011-2020 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 Functions and data declarations.
|
|
*/
|
|
|
|
#ifndef ASTC_CODEC_INTERNALS_INCLUDED
|
|
#define ASTC_CODEC_INTERNALS_INCLUDED
|
|
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
|
|
#include "astc_mathlib.h"
|
|
|
|
// ASTC parameters
|
|
#define MAX_TEXELS_PER_BLOCK 216
|
|
#define MAX_WEIGHTS_PER_BLOCK 64
|
|
#define MIN_WEIGHT_BITS_PER_BLOCK 24
|
|
#define MAX_WEIGHT_BITS_PER_BLOCK 96
|
|
#define PARTITION_BITS 10
|
|
#define PARTITION_COUNT (1 << PARTITION_BITS)
|
|
|
|
// the sum of weights for one texel.
|
|
#define TEXEL_WEIGHT_SUM 16
|
|
#define MAX_DECIMATION_MODES 87
|
|
#define MAX_WEIGHT_MODES 2048
|
|
|
|
enum astc_decode_mode
|
|
{
|
|
DECODE_LDR_SRGB,
|
|
DECODE_LDR,
|
|
DECODE_HDR
|
|
};
|
|
|
|
/*
|
|
Partition table representation:
|
|
For each block size, we have 3 tables, each with 1024 partitionings;
|
|
these three tables correspond to 2, 3 and 4 partitions respectively.
|
|
For each partitioning, we have:
|
|
* a 4-entry table indicating how many texels there are in each of the 4 partitions.
|
|
This may be from 0 to a very large value.
|
|
* a table indicating the partition index of each of the texels in the block.
|
|
Each index may be 0, 1, 2 or 3.
|
|
* Each element in the table is an uint8_t indicating partition index (0, 1, 2 or 3)
|
|
*/
|
|
|
|
struct partition_info
|
|
{
|
|
int partition_count;
|
|
uint8_t partition_of_texel[MAX_TEXELS_PER_BLOCK];
|
|
};
|
|
|
|
/*
|
|
In ASTC, we don't necessarily provide a weight for every texel.
|
|
As such, for each block size, there are a number of patterns where some texels
|
|
have their weights computed as a weighted average of more than 1 weight.
|
|
As such, the codec uses a data structure that tells us: for each texel, which
|
|
weights it is a combination of for each weight, which texels it contributes to.
|
|
The decimation_table is this data structure.
|
|
*/
|
|
struct decimation_table
|
|
{
|
|
int num_weights;
|
|
uint8_t texel_num_weights[MAX_TEXELS_PER_BLOCK]; // number of indices that go into the calculation for a texel
|
|
uint8_t texel_weights_int[MAX_TEXELS_PER_BLOCK][4]; // the weight to assign to each weight
|
|
uint8_t texel_weights[MAX_TEXELS_PER_BLOCK][4]; // the weights that go into a texel calculation
|
|
};
|
|
|
|
/*
|
|
data structure describing information that pertains to a block size and its associated block modes.
|
|
*/
|
|
struct block_mode
|
|
{
|
|
int8_t decimation_mode;
|
|
int8_t quantization_mode;
|
|
int8_t is_dual_plane;
|
|
int8_t permit_decode;
|
|
};
|
|
|
|
struct block_size_descriptor
|
|
{
|
|
int xdim;
|
|
int ydim;
|
|
int zdim;
|
|
int texel_count;
|
|
|
|
int decimation_mode_count;
|
|
const decimation_table *decimation_tables[MAX_DECIMATION_MODES];
|
|
block_mode block_modes[MAX_WEIGHT_MODES];
|
|
|
|
// All the partitioning information for this block size
|
|
partition_info partitions[(3*PARTITION_COUNT)+1];
|
|
};
|
|
|
|
// data structure representing one block of an image.
|
|
// it is expanded to float prior to processing to save some computation time
|
|
// on conversions to/from uint8_t (this also allows us to handle HDR textures easily)
|
|
struct imageblock
|
|
{
|
|
float orig_data[MAX_TEXELS_PER_BLOCK * 4]; // original input data
|
|
float data_r[MAX_TEXELS_PER_BLOCK]; // the data that we will compress, either linear or LNS (0..65535 in both cases)
|
|
float data_g[MAX_TEXELS_PER_BLOCK];
|
|
float data_b[MAX_TEXELS_PER_BLOCK];
|
|
float data_a[MAX_TEXELS_PER_BLOCK];
|
|
|
|
uint8_t rgb_lns[MAX_TEXELS_PER_BLOCK]; // 1 if RGB data are being treated as LNS
|
|
uint8_t alpha_lns[MAX_TEXELS_PER_BLOCK]; // 1 if Alpha data are being treated as LNS
|
|
uint8_t nan_texel[MAX_TEXELS_PER_BLOCK]; // 1 if the texel is a NaN-texel.
|
|
|
|
float red_min, red_max;
|
|
float green_min, green_max;
|
|
float blue_min, blue_max;
|
|
float alpha_min, alpha_max;
|
|
int grayscale; // 1 if R=G=B for every pixel, 0 otherwise
|
|
|
|
int xpos, ypos, zpos;
|
|
};
|
|
|
|
void update_imageblock_flags(
|
|
imageblock* pb,
|
|
int xdim,
|
|
int ydim,
|
|
int zdim);
|
|
|
|
void imageblock_initialize_orig_from_work(
|
|
imageblock * pb,
|
|
int pixelcount);
|
|
|
|
void imageblock_initialize_work_from_orig(
|
|
imageblock * pb,
|
|
int pixelcount);
|
|
|
|
// enumeration of all the quantization methods we support under this format.
|
|
enum quantization_method
|
|
{
|
|
QUANT_2 = 0,
|
|
QUANT_3 = 1,
|
|
QUANT_4 = 2,
|
|
QUANT_5 = 3,
|
|
QUANT_6 = 4,
|
|
QUANT_8 = 5,
|
|
QUANT_10 = 6,
|
|
QUANT_12 = 7,
|
|
QUANT_16 = 8,
|
|
QUANT_20 = 9,
|
|
QUANT_24 = 10,
|
|
QUANT_32 = 11,
|
|
QUANT_40 = 12,
|
|
QUANT_48 = 13,
|
|
QUANT_64 = 14,
|
|
QUANT_80 = 15,
|
|
QUANT_96 = 16,
|
|
QUANT_128 = 17,
|
|
QUANT_160 = 18,
|
|
QUANT_192 = 19,
|
|
QUANT_256 = 20
|
|
};
|
|
|
|
/**
|
|
* @brief Weight quantization transfer table.
|
|
*
|
|
* ASTC can store texel weights at many quantization levels, so for performance
|
|
* we store essential information about each level as a precomputed data
|
|
* structure.
|
|
*
|
|
* Unquantized weights are integers in the range [0, 64], or floats [0, 1].
|
|
*
|
|
* This structure provides the following information:
|
|
* A table, used to estimate the closest quantized
|
|
weight for a given floating-point weight. For each quantized weight, the corresponding unquantized
|
|
and floating-point values. For each quantized weight, a previous-value and a next-value.
|
|
*/
|
|
struct quantization_and_transfer_table
|
|
{
|
|
/** The scrambled unquantized values. */
|
|
uint8_t unquantized_value[32];
|
|
};
|
|
|
|
extern const quantization_and_transfer_table quant_and_xfer_tables[12];
|
|
|
|
enum endpoint_formats
|
|
{
|
|
FMT_LUMINANCE = 0,
|
|
FMT_LUMINANCE_DELTA = 1,
|
|
FMT_HDR_LUMINANCE_LARGE_RANGE = 2,
|
|
FMT_HDR_LUMINANCE_SMALL_RANGE = 3,
|
|
FMT_LUMINANCE_ALPHA = 4,
|
|
FMT_LUMINANCE_ALPHA_DELTA = 5,
|
|
FMT_RGB_SCALE = 6,
|
|
FMT_HDR_RGB_SCALE = 7,
|
|
FMT_RGB = 8,
|
|
FMT_RGB_DELTA = 9,
|
|
FMT_RGB_SCALE_ALPHA = 10,
|
|
FMT_HDR_RGB = 11,
|
|
FMT_RGBA = 12,
|
|
FMT_RGBA_DELTA = 13,
|
|
FMT_HDR_RGB_LDR_ALPHA = 14,
|
|
FMT_HDR_RGBA = 15,
|
|
};
|
|
|
|
struct symbolic_compressed_block
|
|
{
|
|
int error_block; // 1 marks error block, 0 marks non-error-block.
|
|
int block_mode; // 0 to 2047. Negative value marks constant-color block (-1: FP16, -2:UINT16)
|
|
int partition_count; // 1 to 4; Zero marks a constant-color block.
|
|
int partition_index; // 0 to 1023
|
|
int color_formats[4]; // color format for each endpoint color pair.
|
|
int color_formats_matched; // color format for all endpoint pairs are matched.
|
|
int color_values[4][12]; // quantized endpoint color pairs.
|
|
int color_quantization_level;
|
|
uint8_t plane1_weights[MAX_WEIGHTS_PER_BLOCK]; // quantized and decimated weights
|
|
uint8_t plane2_weights[MAX_WEIGHTS_PER_BLOCK];
|
|
int plane2_color_component; // color component for the secondary plane of weights
|
|
int constant_color[4]; // constant-color, as FP16 or UINT16. Used for constant-color blocks only.
|
|
};
|
|
|
|
struct physical_compressed_block
|
|
{
|
|
uint8_t data[16];
|
|
};
|
|
|
|
/* ============================================================================
|
|
Functions and data pertaining to quantization and encoding
|
|
============================================================================ */
|
|
|
|
/**
|
|
* @brief Populate the blocksize descriptor for the target block size.
|
|
*
|
|
* This will also initialize the partition table metadata, which is stored
|
|
* as part of the BSD structure.
|
|
*
|
|
* @param xdim The x axis size of the block.
|
|
* @param ydim The y axis size of the block.
|
|
* @param zdim The z axis size of the block.
|
|
* @param bsd The structure to populate.
|
|
*/
|
|
void init_block_size_descriptor(
|
|
int xdim,
|
|
int ydim,
|
|
int zdim,
|
|
block_size_descriptor* bsd);
|
|
|
|
void term_block_size_descriptor(
|
|
block_size_descriptor* bsd);
|
|
|
|
/**
|
|
* @brief Populate the partition tables for the target block size.
|
|
*
|
|
* Note the block_size_size descriptor must be initialized before calling this
|
|
* function.
|
|
*
|
|
* @param bsd The structure to populate.
|
|
*/
|
|
void init_partition_tables(
|
|
block_size_descriptor* bsd);
|
|
|
|
static inline const partition_info *get_partition_table(
|
|
const block_size_descriptor* bsd,
|
|
int partition_count
|
|
) {
|
|
if (partition_count == 1) {
|
|
partition_count = 5;
|
|
}
|
|
int index = (partition_count - 2) * PARTITION_COUNT;
|
|
return bsd->partitions + index;
|
|
}
|
|
|
|
// ***********************************************************
|
|
// functions and data pertaining to quantization and encoding
|
|
// **********************************************************
|
|
|
|
extern const uint8_t color_unquantization_tables[21][256];
|
|
extern int quantization_mode_table[17][128];
|
|
|
|
void decode_ise(
|
|
int quantization_level,
|
|
int elements,
|
|
const uint8_t* input_data,
|
|
uint8_t* output_data,
|
|
int bit_offset);
|
|
|
|
int compute_ise_bitcount(
|
|
int items,
|
|
quantization_method quant);
|
|
|
|
void build_quantization_mode_table(void);
|
|
|
|
// unpack a pair of color endpoints from a series of integers.
|
|
void unpack_color_endpoints(
|
|
astc_decode_mode decode_mode,
|
|
int format,
|
|
int quantization_level,
|
|
const int* input,
|
|
int* rgb_hdr,
|
|
int* alpha_hdr,
|
|
int* nan_endpoint,
|
|
uint4* output0,
|
|
uint4* output1);
|
|
|
|
/* *********************************** high-level encode and decode functions ************************************ */
|
|
|
|
void decompress_symbolic_block(
|
|
astc_decode_mode decode_mode,
|
|
const block_size_descriptor* bsd,
|
|
int xpos,
|
|
int ypos,
|
|
int zpos,
|
|
const symbolic_compressed_block* scb,
|
|
imageblock* blk);
|
|
|
|
void physical_to_symbolic(
|
|
const block_size_descriptor* bsd,
|
|
physical_compressed_block pb,
|
|
symbolic_compressed_block* res);
|
|
|
|
uint16_t unorm16_to_sf16(
|
|
uint16_t p);
|
|
|
|
uint16_t lns_to_sf16(
|
|
uint16_t p);
|
|
|
|
#endif
|