3537 lines
138 KiB
C++
3537 lines
138 KiB
C++
/*
|
|
|
|
Copyright (c) 2015 Harm Hanemaaijer <fgenfb@yahoo.com>
|
|
|
|
Permission to use, copy, modify, and/or distribute this software for any
|
|
purpose with or without fee is hereby granted, provided that the above
|
|
copyright notice and this permission notice appear in all copies.
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
*/
|
|
|
|
#include "AndroidETC.h"
|
|
#include "CoreMinimal.h"
|
|
#include "GenericPlatform/GenericPlatformMath.h"
|
|
#include "AndroidETC.h"
|
|
#include "AndroidETCInternal.h"
|
|
#include "RHI.h"
|
|
|
|
IMPLEMENT_MODULE( Fdetex, detex );
|
|
|
|
Fdetex::Fdetex()
|
|
{
|
|
}
|
|
|
|
Fdetex::~Fdetex()
|
|
{
|
|
}
|
|
|
|
void Fdetex::StartupModule()
|
|
{
|
|
}
|
|
|
|
void Fdetex::ShutdownModule()
|
|
{
|
|
}
|
|
|
|
/* Maximum uncompressed block size in bytes. */
|
|
#define DETEX_MAX_BLOCK_SIZE 256
|
|
|
|
/* Compressed texture format definitions for general texture decompression */
|
|
/* functions. */
|
|
|
|
#define DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(n) ((uint32_t)n << 24)
|
|
|
|
/* Mode mask flags. */
|
|
|
|
enum
|
|
{
|
|
DETEX_MODE_MASK_ETC_INDIVIDUAL = 0x1,
|
|
DETEX_MODE_MASK_ETC_DIFFERENTIAL = 0x2,
|
|
DETEX_MODE_MASK_ETC_T = 0x4,
|
|
DETEX_MODE_MASK_ETC_H = 0x8,
|
|
DETEX_MODE_MASK_ETC_PLANAR = 0x10,
|
|
DETEX_MODE_MASK_ALL_MODES_ETC1 = 0x3,
|
|
DETEX_MODE_MASK_ALL_MODES_ETC2 = 0x1F,
|
|
DETEX_MODE_MASK_ALL_MODES_ETC2_PUNCHTHROUGH = 0X1E,
|
|
DETEX_MODE_MASK_ALL_MODES_BPTC = 0xFF,
|
|
DETEX_MODE_MASK_ALL_MODES_BPTC_FLOAT = 0x3FFF,
|
|
DETEX_MODE_MASK_ALL = 0XFFFFFFFF,
|
|
};
|
|
|
|
/* Decompression function flags. */
|
|
|
|
enum
|
|
{
|
|
/* Function returns false (invalid block) when the compressed block */
|
|
/* is in a format not allowed to be generated by an encoder. */
|
|
DETEX_DECOMPRESS_FLAG_ENCODE = 0x1,
|
|
/* For compression formats that have opaque and non-opaque modes, */
|
|
/* return false (invalid block) when the compressed block is encoded */
|
|
/* using a non-opaque mode. */
|
|
DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY = 0x2,
|
|
/* For compression formats that have opaque and non-opaque modes, */
|
|
/* return false (invalid block) when the compressed block is encoded */
|
|
/* using an opaque mode. */
|
|
DETEX_DECOMPRESS_FLAG_NON_OPAQUE_ONLY = 0x4,
|
|
};
|
|
|
|
enum
|
|
{
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_UNCOMPRESSED = 0,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1 = 1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT1 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_S3TC = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT1A = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT3 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_DXT5 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC4_UNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC4_SNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC5_UNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC5_SNORM = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC6H_UF16 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC6H_SF16 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC7 = DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC1,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_PUNCHTHROUGH,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_EAC,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_R11,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_R11,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_RG11,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_RG11,
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ASTC_4X4,
|
|
};
|
|
|
|
typedef struct
|
|
{
|
|
uint32_t texture_format;
|
|
int ktx_support;
|
|
int dds_support;
|
|
const char *text1;
|
|
const char *text2;
|
|
int block_width; // The block width (1 for uncompressed textures).
|
|
int block_height; // The block height (1 for uncompressed textures).
|
|
int gl_internal_format;
|
|
uint32_t gl_format;
|
|
uint32_t gl_type;
|
|
const char *dx_four_cc;
|
|
int dx10_format;
|
|
} detexTextureFileInfo;
|
|
|
|
enum
|
|
{
|
|
DETEX_TEXTURE_FORMAT_PIXEL_FORMAT_MASK = 0x0000FFFF,
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT = 0x00800000,
|
|
DETEX_TEXTURE_FORMAT_BC1 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1) |
|
|
DETEX_PIXEL_FORMAT_RGBX8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_BC1A = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC1A) |
|
|
DETEX_PIXEL_FORMAT_RGBA8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_BC2 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC2) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_RGBA8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_BC3 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BC3) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_RGBA8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_RGTC1 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC1) |
|
|
DETEX_PIXEL_FORMAT_R8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_SIGNED_RGTC1 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC1) |
|
|
DETEX_PIXEL_FORMAT_SIGNED_R16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_RGTC2 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_RGTC2) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_RG8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_SIGNED_RGTC2 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_SIGNED_RGTC2) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_SIGNED_RG16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_BPTC_FLOAT = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_FLOAT) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_FLOAT_RGBX16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_BPTC_SIGNED_FLOAT = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC_SIGNED_FLOAT) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_BPTC = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_BPTC) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_RGBA8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_ETC1 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC1) |
|
|
DETEX_PIXEL_FORMAT_RGBX8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_ETC2 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2) |
|
|
DETEX_PIXEL_FORMAT_RGBX8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_ETC2_PUNCHTHROUGH = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_PUNCHTHROUGH) |
|
|
DETEX_PIXEL_FORMAT_RGBA8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_ETC2_EAC = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ETC2_EAC) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_RGBA8
|
|
),
|
|
DETEX_TEXTURE_FORMAT_EAC_R11 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_R11) |
|
|
DETEX_PIXEL_FORMAT_R16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_EAC_SIGNED_R11 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_R11) |
|
|
DETEX_PIXEL_FORMAT_SIGNED_R16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_EAC_RG11 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_RG11) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_RG16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_EAC_SIGNED_RG11 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_EAC_SIGNED_RG11) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_SIGNED_RG16
|
|
),
|
|
DETEX_TEXTURE_FORMAT_ASTC_4X4 = (
|
|
DETEX_TEXTURE_FORMAT_COMPRESSED_FORMAT_BITS(
|
|
DETEX_COMPRESSED_TEXTURE_FORMAT_INDEX_ASTC_4X4) |
|
|
DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT |
|
|
DETEX_PIXEL_FORMAT_RGBA8
|
|
),
|
|
};
|
|
|
|
static const detexTextureFileInfo texture_info[] =
|
|
{
|
|
// Texture format KTX/DDS Textual representations Block
|
|
// support size OpenGL ID in KTX files DDS file IDs
|
|
// internalFormat, format, type FourCC, DX10 format
|
|
// Compressed formats.
|
|
{ DETEX_TEXTURE_FORMAT_BC1, 1, 1, "BC1", "DXT1", 4, 4, 0x83F0, 0, 0, "DXT1", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_BC1A, 1, 1, "BC1A", "DXT1A", 4, 4, 0x83F1, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_BC2, 1, 1, "BC2", "DXT3", 4, 4, 0x83F2, 0, 0, "DXT3", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_BC3, 1, 1, "BC3", "DXT5", 4, 4, 0x83F3, 0, 0, "DXT5", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_RGTC1, 1, 1, "RGTC1", "BC4_UNORM", 4, 4, 0x8DBB, 0, 0, "DX10", 80 },
|
|
{ DETEX_TEXTURE_FORMAT_SIGNED_RGTC1, 1, 1, "SIGNED_RGTC1", "BC4_SNORM", 4, 4, 0x8DBC, 0, 0, "DX10", 81 },
|
|
{ DETEX_TEXTURE_FORMAT_RGTC2, 1, 1, "RGTC2", "BC5_UNORM", 4, 4, 0x8DBD, 0, 0, "DX10", 83 },
|
|
{ DETEX_TEXTURE_FORMAT_SIGNED_RGTC2, 1, 1, "SIGNED_RGTC2", "BC5_SNORM", 4, 4, 0x8DBE, 0, 0, "DX10", 84 },
|
|
{ DETEX_TEXTURE_FORMAT_BPTC_FLOAT, 1, 1, "BPTC_FLOAT", "BC6H_UF16", 4, 4, 0x8E8F, 0, 0, "DX10", 95 },
|
|
{ DETEX_TEXTURE_FORMAT_BPTC_SIGNED_FLOAT, 1, 1, "BPTC_SIGNED_FLOAT", "BC6H_SF16", 4, 4, 0x8E8E, 0, 0, "DX10", 96 },
|
|
{ DETEX_TEXTURE_FORMAT_BPTC, 1, 1, "BPTC", "BC7", 4, 4, 0x8E8C, 0, 0, "DX10", 98 },
|
|
{ DETEX_TEXTURE_FORMAT_ETC1, 1, 0, "ETC1", "", 4, 4, 0x8D64, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_ETC2, 1, 0, "ETC2", "ETC2_RGB8", 4, 4, 0x9274, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_ETC2_PUNCHTHROUGH, 1, 0, "ETC2_PUNCHTHROUGH", "", 4, 4, 0x9275, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_ETC2_EAC, 1, 0, "ETC2_EAC", "EAC", 4, 4, 0x9278, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_EAC_R11, 1, 0, "EAC_R11", "", 4, 4, 0x9270, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_EAC_SIGNED_R11, 1, 0, "EAC_SIGNED_R11", "", 4, 4, 0x9271, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_EAC_RG11, 1, 0, "EAC_RG11", "", 4, 4, 0x9272, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_EAC_SIGNED_RG11, 1, 0, "EAC_SIGNED_RG11", "", 4, 4, 0x9273, 0, 0, "", 0 },
|
|
{ DETEX_TEXTURE_FORMAT_ASTC_4X4, 1, 0, "ASTC_4x4", "", 4, 4, 0x93B0, 0, 0, "DX10", 134 }
|
|
};
|
|
|
|
#define DETEX_NU_TEXTURE_INFO_ENTRIES (sizeof(texture_info) / sizeof(texture_info[0]))
|
|
|
|
|
|
|
|
const uint8_t detex_bptc_table_P2[64 * 16] = {
|
|
0,0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,
|
|
0,0,0,1,0,0,0,1,0,0,0,1,0,0,0,1,
|
|
0,1,1,1,0,1,1,1,0,1,1,1,0,1,1,1,
|
|
0,0,0,1,0,0,1,1,0,0,1,1,0,1,1,1,
|
|
0,0,0,0,0,0,0,1,0,0,0,1,0,0,1,1,
|
|
0,0,1,1,0,1,1,1,0,1,1,1,1,1,1,1,
|
|
0,0,0,1,0,0,1,1,0,1,1,1,1,1,1,1,
|
|
0,0,0,0,0,0,0,1,0,0,1,1,0,1,1,1,
|
|
0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,1,
|
|
0,0,1,1,0,1,1,1,1,1,1,1,1,1,1,1,
|
|
0,0,0,0,0,0,0,1,0,1,1,1,1,1,1,1,
|
|
0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,
|
|
0,0,0,1,0,1,1,1,1,1,1,1,1,1,1,1,
|
|
0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,
|
|
0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,1,
|
|
0,0,0,0,1,0,0,0,1,1,1,0,1,1,1,1,
|
|
0,1,1,1,0,0,0,1,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,0,0,0,0,1,0,0,0,1,1,1,0,
|
|
0,1,1,1,0,0,1,1,0,0,0,1,0,0,0,0,
|
|
0,0,1,1,0,0,0,1,0,0,0,0,0,0,0,0,
|
|
0,0,0,0,1,0,0,0,1,1,0,0,1,1,1,0,
|
|
0,0,0,0,0,0,0,0,1,0,0,0,1,1,0,0,
|
|
0,1,1,1,0,0,1,1,0,0,1,1,0,0,0,1,
|
|
0,0,1,1,0,0,0,1,0,0,0,1,0,0,0,0,
|
|
0,0,0,0,1,0,0,0,1,0,0,0,1,1,0,0,
|
|
0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0,
|
|
0,0,1,1,0,1,1,0,0,1,1,0,1,1,0,0,
|
|
0,0,0,1,0,1,1,1,1,1,1,0,1,0,0,0,
|
|
0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0,
|
|
0,1,1,1,0,0,0,1,1,0,0,0,1,1,1,0,
|
|
0,0,1,1,1,0,0,1,1,0,0,1,1,1,0,0,
|
|
0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,
|
|
0,0,0,0,1,1,1,1,0,0,0,0,1,1,1,1,
|
|
0,1,0,1,1,0,1,0,0,1,0,1,1,0,1,0,
|
|
0,0,1,1,0,0,1,1,1,1,0,0,1,1,0,0,
|
|
0,0,1,1,1,1,0,0,0,0,1,1,1,1,0,0,
|
|
0,1,0,1,0,1,0,1,1,0,1,0,1,0,1,0,
|
|
0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,
|
|
0,1,0,1,1,0,1,0,1,0,1,0,0,1,0,1,
|
|
0,1,1,1,0,0,1,1,1,1,0,0,1,1,1,0,
|
|
0,0,0,1,0,0,1,1,1,1,0,0,1,0,0,0,
|
|
0,0,1,1,0,0,1,0,0,1,0,0,1,1,0,0,
|
|
0,0,1,1,1,0,1,1,1,1,0,1,1,1,0,0,
|
|
0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
|
|
0,0,1,1,1,1,0,0,1,1,0,0,0,0,1,1,
|
|
0,1,1,0,0,1,1,0,1,0,0,1,1,0,0,1,
|
|
0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0,
|
|
0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,0,
|
|
0,0,1,0,0,1,1,1,0,0,1,0,0,0,0,0,
|
|
0,0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,
|
|
0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0,
|
|
0,1,1,0,1,1,0,0,1,0,0,1,0,0,1,1,
|
|
0,0,1,1,0,1,1,0,1,1,0,0,1,0,0,1,
|
|
0,1,1,0,0,0,1,1,1,0,0,1,1,1,0,0,
|
|
0,0,1,1,1,0,0,1,1,1,0,0,0,1,1,0,
|
|
0,1,1,0,1,1,0,0,1,1,0,0,1,0,0,1,
|
|
0,1,1,0,0,0,1,1,0,0,1,1,1,0,0,1,
|
|
0,1,1,1,1,1,1,0,1,0,0,0,0,0,0,1,
|
|
0,0,0,1,1,0,0,0,1,1,1,0,0,1,1,1,
|
|
0,0,0,0,1,1,1,1,0,0,1,1,0,0,1,1,
|
|
0,0,1,1,0,0,1,1,1,1,1,1,0,0,0,0,
|
|
0,0,1,0,0,0,1,0,1,1,1,0,1,1,1,0,
|
|
0,1,0,0,0,1,0,0,0,1,1,1,0,1,1,1
|
|
};
|
|
|
|
const uint8_t detex_bptc_table_P3[64 * 16] = {
|
|
0,0,1,1,0,0,1,1,0,2,2,1,2,2,2,2,
|
|
0,0,0,1,0,0,1,1,2,2,1,1,2,2,2,1,
|
|
0,0,0,0,2,0,0,1,2,2,1,1,2,2,1,1,
|
|
0,2,2,2,0,0,2,2,0,0,1,1,0,1,1,1,
|
|
0,0,0,0,0,0,0,0,1,1,2,2,1,1,2,2,
|
|
0,0,1,1,0,0,1,1,0,0,2,2,0,0,2,2,
|
|
0,0,2,2,0,0,2,2,1,1,1,1,1,1,1,1,
|
|
0,0,1,1,0,0,1,1,2,2,1,1,2,2,1,1,
|
|
0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,
|
|
0,0,0,0,1,1,1,1,1,1,1,1,2,2,2,2,
|
|
0,0,0,0,1,1,1,1,2,2,2,2,2,2,2,2,
|
|
0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,
|
|
0,1,1,2,0,1,1,2,0,1,1,2,0,1,1,2,
|
|
0,1,2,2,0,1,2,2,0,1,2,2,0,1,2,2,
|
|
0,0,1,1,0,1,1,2,1,1,2,2,1,2,2,2,
|
|
0,0,1,1,2,0,0,1,2,2,0,0,2,2,2,0,
|
|
0,0,0,1,0,0,1,1,0,1,1,2,1,1,2,2,
|
|
0,1,1,1,0,0,1,1,2,0,0,1,2,2,0,0,
|
|
0,0,0,0,1,1,2,2,1,1,2,2,1,1,2,2,
|
|
0,0,2,2,0,0,2,2,0,0,2,2,1,1,1,1,
|
|
0,1,1,1,0,1,1,1,0,2,2,2,0,2,2,2,
|
|
0,0,0,1,0,0,0,1,2,2,2,1,2,2,2,1,
|
|
0,0,0,0,0,0,1,1,0,1,2,2,0,1,2,2,
|
|
0,0,0,0,1,1,0,0,2,2,1,0,2,2,1,0,
|
|
0,1,2,2,0,1,2,2,0,0,1,1,0,0,0,0,
|
|
0,0,1,2,0,0,1,2,1,1,2,2,2,2,2,2,
|
|
0,1,1,0,1,2,2,1,1,2,2,1,0,1,1,0,
|
|
0,0,0,0,0,1,1,0,1,2,2,1,1,2,2,1,
|
|
0,0,2,2,1,1,0,2,1,1,0,2,0,0,2,2,
|
|
0,1,1,0,0,1,1,0,2,0,0,2,2,2,2,2,
|
|
0,0,1,1,0,1,2,2,0,1,2,2,0,0,1,1,
|
|
0,0,0,0,2,0,0,0,2,2,1,1,2,2,2,1,
|
|
0,0,0,0,0,0,0,2,1,1,2,2,1,2,2,2,
|
|
0,2,2,2,0,0,2,2,0,0,1,2,0,0,1,1,
|
|
0,0,1,1,0,0,1,2,0,0,2,2,0,2,2,2,
|
|
0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,
|
|
0,0,0,0,1,1,1,1,2,2,2,2,0,0,0,0,
|
|
0,1,2,0,1,2,0,1,2,0,1,2,0,1,2,0,
|
|
0,1,2,0,2,0,1,2,1,2,0,1,0,1,2,0,
|
|
0,0,1,1,2,2,0,0,1,1,2,2,0,0,1,1,
|
|
0,0,1,1,1,1,2,2,2,2,0,0,0,0,1,1,
|
|
0,1,0,1,0,1,0,1,2,2,2,2,2,2,2,2,
|
|
0,0,0,0,0,0,0,0,2,1,2,1,2,1,2,1,
|
|
0,0,2,2,1,1,2,2,0,0,2,2,1,1,2,2,
|
|
0,0,2,2,0,0,1,1,0,0,2,2,0,0,1,1,
|
|
0,2,2,0,1,2,2,1,0,2,2,0,1,2,2,1,
|
|
0,1,0,1,2,2,2,2,2,2,2,2,0,1,0,1,
|
|
0,0,0,0,2,1,2,1,2,1,2,1,2,1,2,1,
|
|
0,1,0,1,0,1,0,1,0,1,0,1,2,2,2,2,
|
|
0,2,2,2,0,1,1,1,0,2,2,2,0,1,1,1,
|
|
0,0,0,2,1,1,1,2,0,0,0,2,1,1,1,2,
|
|
0,0,0,0,2,1,1,2,2,1,1,2,2,1,1,2,
|
|
0,2,2,2,0,1,1,1,0,1,1,1,0,2,2,2,
|
|
0,0,0,2,1,1,1,2,1,1,1,2,0,0,0,2,
|
|
0,1,1,0,0,1,1,0,0,1,1,0,2,2,2,2,
|
|
0,0,0,0,0,0,0,0,2,1,1,2,2,1,1,2,
|
|
0,1,1,0,0,1,1,0,2,2,2,2,2,2,2,2,
|
|
0,0,2,2,0,0,1,1,0,0,1,1,0,0,2,2,
|
|
0,0,2,2,1,1,2,2,1,1,2,2,0,0,2,2,
|
|
0,0,0,0,0,0,0,0,0,0,0,0,2,1,1,2,
|
|
0,0,0,2,0,0,0,1,0,0,0,2,0,0,0,1,
|
|
0,2,2,2,1,2,2,2,0,2,2,2,1,2,2,2,
|
|
0,1,0,1,2,2,2,2,2,2,2,2,2,2,2,2,
|
|
0,1,1,1,2,0,1,1,2,2,0,1,2,2,2,0,
|
|
};
|
|
|
|
const uint8_t detex_bptc_table_anchor_index_second_subset[64] = {
|
|
15, 15,15,15,15,15,15,15,
|
|
15, 15,15,15,15,15,15,15,
|
|
15, 2, 8, 2, 2, 8, 8,15,
|
|
2, 8, 2, 2, 8, 8, 2, 2,
|
|
15, 15, 6, 8, 2, 8,15,15,
|
|
2, 8, 2, 2, 2,15,15, 6,
|
|
6, 2, 6, 8,15,15, 2, 2,
|
|
15, 15,15,15,15, 2, 2,15
|
|
};
|
|
|
|
const uint8_t detex_bptc_table_anchor_index_second_subset_of_three[64] = {
|
|
3, 3, 15, 15, 8, 3, 15, 15,
|
|
8, 8, 6, 6, 6, 5, 3, 3,
|
|
3, 3, 8, 15, 3, 3, 6, 10,
|
|
5, 8, 8, 6, 8, 5, 15, 15,
|
|
8, 15, 3, 5, 6, 10, 8, 15,
|
|
15, 3, 15, 5, 15, 15, 15, 15,
|
|
3, 15, 5, 5, 5, 8, 5, 10,
|
|
5, 10, 8, 13, 15, 12, 3, 3
|
|
};
|
|
|
|
const uint8_t detex_bptc_table_anchor_index_third_subset[64] = {
|
|
15, 8, 8, 3,15,15, 3, 8,
|
|
15,15,15,15,15,15,15, 8,
|
|
15, 8,15, 3,15, 8,15, 8,
|
|
3,15, 6,10,15,15,10, 8,
|
|
15, 3,15,10,10, 8, 9,10,
|
|
6,15, 8,15, 3, 6, 6, 8,
|
|
15, 3,15,15,15,15,15,15,
|
|
15,15,15,15, 3,15,15, 8
|
|
};
|
|
|
|
const uint16_t detex_bptc_table_aWeight2[4] = { 0, 21, 43, 64 };
|
|
|
|
const uint16_t detex_bptc_table_aWeight3[8] = { 0, 9, 18, 27, 37, 46, 55, 64 };
|
|
|
|
const uint16_t detex_bptc_table_aWeight4[16] = {
|
|
0, 4, 9, 13, 17, 21, 26, 30,
|
|
34, 38, 43, 47, 51, 55, 60, 64
|
|
};
|
|
|
|
static const int8_t map_mode_table[32] = {
|
|
0, 1, 2, 10, -1, -1, 3, 11, -1, -1, 4, 12, -1, -1, 5, 13,
|
|
-1, -1, 6, -1, -1, -1, 7, -1, -1, -1, 8, -1, -1, -1, 9, -1
|
|
};
|
|
|
|
static const uint8_t bptc_float_EPB[14] = { 10, 7, 11, 11, 11, 9, 8, 8, 8, 6, 10, 11, 12, 16 };
|
|
|
|
static const int complement3bitshifted_table[8] = { 0, 8, 16, 24, -32, -24, -16, -8 };
|
|
|
|
static const int modifier_table[8][4] = {
|
|
{ 2, 8, -2, -8 },
|
|
{ 5, 17, -5, -17 },
|
|
{ 9, 29, -9, -29 },
|
|
{ 13, 42, -13, -42 },
|
|
{ 18, 60, -18, -60 },
|
|
{ 24, 80, -24, -80 },
|
|
{ 33, 106, -33, -106 },
|
|
{ 47, 183, -47, -183 }
|
|
};
|
|
|
|
const uint8_t detex_division_by_3_table[768] =
|
|
{
|
|
0, 0, 0, 1, 1, 1, 2, 2,
|
|
2, 3, 3, 3, 4, 4, 4, 5,
|
|
5, 5, 6, 6, 6, 7, 7, 7,
|
|
8, 8, 8, 9, 9, 9, 10, 10,
|
|
10, 11, 11, 11, 12, 12, 12, 13,
|
|
13, 13, 14, 14, 14, 15, 15, 15,
|
|
16, 16, 16, 17, 17, 17, 18, 18,
|
|
18, 19, 19, 19, 20, 20, 20, 21,
|
|
21, 21, 22, 22, 22, 23, 23, 23,
|
|
24, 24, 24, 25, 25, 25, 26, 26,
|
|
26, 27, 27, 27, 28, 28, 28, 29,
|
|
29, 29, 30, 30, 30, 31, 31, 31,
|
|
32, 32, 32, 33, 33, 33, 34, 34,
|
|
34, 35, 35, 35, 36, 36, 36, 37,
|
|
37, 37, 38, 38, 38, 39, 39, 39,
|
|
40, 40, 40, 41, 41, 41, 42, 42,
|
|
42, 43, 43, 43, 44, 44, 44, 45,
|
|
45, 45, 46, 46, 46, 47, 47, 47,
|
|
48, 48, 48, 49, 49, 49, 50, 50,
|
|
50, 51, 51, 51, 52, 52, 52, 53,
|
|
53, 53, 54, 54, 54, 55, 55, 55,
|
|
56, 56, 56, 57, 57, 57, 58, 58,
|
|
58, 59, 59, 59, 60, 60, 60, 61,
|
|
61, 61, 62, 62, 62, 63, 63, 63,
|
|
64, 64, 64, 65, 65, 65, 66, 66,
|
|
66, 67, 67, 67, 68, 68, 68, 69,
|
|
69, 69, 70, 70, 70, 71, 71, 71,
|
|
72, 72, 72, 73, 73, 73, 74, 74,
|
|
74, 75, 75, 75, 76, 76, 76, 77,
|
|
77, 77, 78, 78, 78, 79, 79, 79,
|
|
80, 80, 80, 81, 81, 81, 82, 82,
|
|
82, 83, 83, 83, 84, 84, 84, 85,
|
|
85, 85, 86, 86, 86, 87, 87, 87,
|
|
88, 88, 88, 89, 89, 89, 90, 90,
|
|
90, 91, 91, 91, 92, 92, 92, 93,
|
|
93, 93, 94, 94, 94, 95, 95, 95,
|
|
96, 96, 96, 97, 97, 97, 98, 98,
|
|
98, 99, 99, 99, 100, 100, 100, 101,
|
|
101, 101, 102, 102, 102, 103, 103, 103,
|
|
104, 104, 104, 105, 105, 105, 106, 106,
|
|
106, 107, 107, 107, 108, 108, 108, 109,
|
|
109, 109, 110, 110, 110, 111, 111, 111,
|
|
112, 112, 112, 113, 113, 113, 114, 114,
|
|
114, 115, 115, 115, 116, 116, 116, 117,
|
|
117, 117, 118, 118, 118, 119, 119, 119,
|
|
120, 120, 120, 121, 121, 121, 122, 122,
|
|
122, 123, 123, 123, 124, 124, 124, 125,
|
|
125, 125, 126, 126, 126, 127, 127, 127,
|
|
128, 128, 128, 129, 129, 129, 130, 130,
|
|
130, 131, 131, 131, 132, 132, 132, 133,
|
|
133, 133, 134, 134, 134, 135, 135, 135,
|
|
136, 136, 136, 137, 137, 137, 138, 138,
|
|
138, 139, 139, 139, 140, 140, 140, 141,
|
|
141, 141, 142, 142, 142, 143, 143, 143,
|
|
144, 144, 144, 145, 145, 145, 146, 146,
|
|
146, 147, 147, 147, 148, 148, 148, 149,
|
|
149, 149, 150, 150, 150, 151, 151, 151,
|
|
152, 152, 152, 153, 153, 153, 154, 154,
|
|
154, 155, 155, 155, 156, 156, 156, 157,
|
|
157, 157, 158, 158, 158, 159, 159, 159,
|
|
160, 160, 160, 161, 161, 161, 162, 162,
|
|
162, 163, 163, 163, 164, 164, 164, 165,
|
|
165, 165, 166, 166, 166, 167, 167, 167,
|
|
168, 168, 168, 169, 169, 169, 170, 170,
|
|
170, 171, 171, 171, 172, 172, 172, 173,
|
|
173, 173, 174, 174, 174, 175, 175, 175,
|
|
176, 176, 176, 177, 177, 177, 178, 178,
|
|
178, 179, 179, 179, 180, 180, 180, 181,
|
|
181, 181, 182, 182, 182, 183, 183, 183,
|
|
184, 184, 184, 185, 185, 185, 186, 186,
|
|
186, 187, 187, 187, 188, 188, 188, 189,
|
|
189, 189, 190, 190, 190, 191, 191, 191,
|
|
192, 192, 192, 193, 193, 193, 194, 194,
|
|
194, 195, 195, 195, 196, 196, 196, 197,
|
|
197, 197, 198, 198, 198, 199, 199, 199,
|
|
200, 200, 200, 201, 201, 201, 202, 202,
|
|
202, 203, 203, 203, 204, 204, 204, 205,
|
|
205, 205, 206, 206, 206, 207, 207, 207,
|
|
208, 208, 208, 209, 209, 209, 210, 210,
|
|
210, 211, 211, 211, 212, 212, 212, 213,
|
|
213, 213, 214, 214, 214, 215, 215, 215,
|
|
216, 216, 216, 217, 217, 217, 218, 218,
|
|
218, 219, 219, 219, 220, 220, 220, 221,
|
|
221, 221, 222, 222, 222, 223, 223, 223,
|
|
224, 224, 224, 225, 225, 225, 226, 226,
|
|
226, 227, 227, 227, 228, 228, 228, 229,
|
|
229, 229, 230, 230, 230, 231, 231, 231,
|
|
232, 232, 232, 233, 233, 233, 234, 234,
|
|
234, 235, 235, 235, 236, 236, 236, 237,
|
|
237, 237, 238, 238, 238, 239, 239, 239,
|
|
240, 240, 240, 241, 241, 241, 242, 242,
|
|
242, 243, 243, 243, 244, 244, 244, 245,
|
|
245, 245, 246, 246, 246, 247, 247, 247,
|
|
248, 248, 248, 249, 249, 249, 250, 250,
|
|
250, 251, 251, 251, 252, 252, 252, 253,
|
|
253, 253, 254, 254, 254, 255, 255, 255,
|
|
};
|
|
|
|
const uint8_t detex_division_by_7_table[1792] =
|
|
{
|
|
0, 0, 0, 0, 0, 0, 0, 1,
|
|
1, 1, 1, 1, 1, 1, 2, 2,
|
|
2, 2, 2, 2, 2, 3, 3, 3,
|
|
3, 3, 3, 3, 4, 4, 4, 4,
|
|
4, 4, 4, 5, 5, 5, 5, 5,
|
|
5, 5, 6, 6, 6, 6, 6, 6,
|
|
6, 7, 7, 7, 7, 7, 7, 7,
|
|
8, 8, 8, 8, 8, 8, 8, 9,
|
|
9, 9, 9, 9, 9, 9, 10, 10,
|
|
10, 10, 10, 10, 10, 11, 11, 11,
|
|
11, 11, 11, 11, 12, 12, 12, 12,
|
|
12, 12, 12, 13, 13, 13, 13, 13,
|
|
13, 13, 14, 14, 14, 14, 14, 14,
|
|
14, 15, 15, 15, 15, 15, 15, 15,
|
|
16, 16, 16, 16, 16, 16, 16, 17,
|
|
17, 17, 17, 17, 17, 17, 18, 18,
|
|
18, 18, 18, 18, 18, 19, 19, 19,
|
|
19, 19, 19, 19, 20, 20, 20, 20,
|
|
20, 20, 20, 21, 21, 21, 21, 21,
|
|
21, 21, 22, 22, 22, 22, 22, 22,
|
|
22, 23, 23, 23, 23, 23, 23, 23,
|
|
24, 24, 24, 24, 24, 24, 24, 25,
|
|
25, 25, 25, 25, 25, 25, 26, 26,
|
|
26, 26, 26, 26, 26, 27, 27, 27,
|
|
27, 27, 27, 27, 28, 28, 28, 28,
|
|
28, 28, 28, 29, 29, 29, 29, 29,
|
|
29, 29, 30, 30, 30, 30, 30, 30,
|
|
30, 31, 31, 31, 31, 31, 31, 31,
|
|
32, 32, 32, 32, 32, 32, 32, 33,
|
|
33, 33, 33, 33, 33, 33, 34, 34,
|
|
34, 34, 34, 34, 34, 35, 35, 35,
|
|
35, 35, 35, 35, 36, 36, 36, 36,
|
|
36, 36, 36, 37, 37, 37, 37, 37,
|
|
37, 37, 38, 38, 38, 38, 38, 38,
|
|
38, 39, 39, 39, 39, 39, 39, 39,
|
|
40, 40, 40, 40, 40, 40, 40, 41,
|
|
41, 41, 41, 41, 41, 41, 42, 42,
|
|
42, 42, 42, 42, 42, 43, 43, 43,
|
|
43, 43, 43, 43, 44, 44, 44, 44,
|
|
44, 44, 44, 45, 45, 45, 45, 45,
|
|
45, 45, 46, 46, 46, 46, 46, 46,
|
|
46, 47, 47, 47, 47, 47, 47, 47,
|
|
48, 48, 48, 48, 48, 48, 48, 49,
|
|
49, 49, 49, 49, 49, 49, 50, 50,
|
|
50, 50, 50, 50, 50, 51, 51, 51,
|
|
51, 51, 51, 51, 52, 52, 52, 52,
|
|
52, 52, 52, 53, 53, 53, 53, 53,
|
|
53, 53, 54, 54, 54, 54, 54, 54,
|
|
54, 55, 55, 55, 55, 55, 55, 55,
|
|
56, 56, 56, 56, 56, 56, 56, 57,
|
|
57, 57, 57, 57, 57, 57, 58, 58,
|
|
58, 58, 58, 58, 58, 59, 59, 59,
|
|
59, 59, 59, 59, 60, 60, 60, 60,
|
|
60, 60, 60, 61, 61, 61, 61, 61,
|
|
61, 61, 62, 62, 62, 62, 62, 62,
|
|
62, 63, 63, 63, 63, 63, 63, 63,
|
|
64, 64, 64, 64, 64, 64, 64, 65,
|
|
65, 65, 65, 65, 65, 65, 66, 66,
|
|
66, 66, 66, 66, 66, 67, 67, 67,
|
|
67, 67, 67, 67, 68, 68, 68, 68,
|
|
68, 68, 68, 69, 69, 69, 69, 69,
|
|
69, 69, 70, 70, 70, 70, 70, 70,
|
|
70, 71, 71, 71, 71, 71, 71, 71,
|
|
72, 72, 72, 72, 72, 72, 72, 73,
|
|
73, 73, 73, 73, 73, 73, 74, 74,
|
|
74, 74, 74, 74, 74, 75, 75, 75,
|
|
75, 75, 75, 75, 76, 76, 76, 76,
|
|
76, 76, 76, 77, 77, 77, 77, 77,
|
|
77, 77, 78, 78, 78, 78, 78, 78,
|
|
78, 79, 79, 79, 79, 79, 79, 79,
|
|
80, 80, 80, 80, 80, 80, 80, 81,
|
|
81, 81, 81, 81, 81, 81, 82, 82,
|
|
82, 82, 82, 82, 82, 83, 83, 83,
|
|
83, 83, 83, 83, 84, 84, 84, 84,
|
|
84, 84, 84, 85, 85, 85, 85, 85,
|
|
85, 85, 86, 86, 86, 86, 86, 86,
|
|
86, 87, 87, 87, 87, 87, 87, 87,
|
|
88, 88, 88, 88, 88, 88, 88, 89,
|
|
89, 89, 89, 89, 89, 89, 90, 90,
|
|
90, 90, 90, 90, 90, 91, 91, 91,
|
|
91, 91, 91, 91, 92, 92, 92, 92,
|
|
92, 92, 92, 93, 93, 93, 93, 93,
|
|
93, 93, 94, 94, 94, 94, 94, 94,
|
|
94, 95, 95, 95, 95, 95, 95, 95,
|
|
96, 96, 96, 96, 96, 96, 96, 97,
|
|
97, 97, 97, 97, 97, 97, 98, 98,
|
|
98, 98, 98, 98, 98, 99, 99, 99,
|
|
99, 99, 99, 99, 100, 100, 100, 100,
|
|
100, 100, 100, 101, 101, 101, 101, 101,
|
|
101, 101, 102, 102, 102, 102, 102, 102,
|
|
102, 103, 103, 103, 103, 103, 103, 103,
|
|
104, 104, 104, 104, 104, 104, 104, 105,
|
|
105, 105, 105, 105, 105, 105, 106, 106,
|
|
106, 106, 106, 106, 106, 107, 107, 107,
|
|
107, 107, 107, 107, 108, 108, 108, 108,
|
|
108, 108, 108, 109, 109, 109, 109, 109,
|
|
109, 109, 110, 110, 110, 110, 110, 110,
|
|
110, 111, 111, 111, 111, 111, 111, 111,
|
|
112, 112, 112, 112, 112, 112, 112, 113,
|
|
113, 113, 113, 113, 113, 113, 114, 114,
|
|
114, 114, 114, 114, 114, 115, 115, 115,
|
|
115, 115, 115, 115, 116, 116, 116, 116,
|
|
116, 116, 116, 117, 117, 117, 117, 117,
|
|
117, 117, 118, 118, 118, 118, 118, 118,
|
|
118, 119, 119, 119, 119, 119, 119, 119,
|
|
120, 120, 120, 120, 120, 120, 120, 121,
|
|
121, 121, 121, 121, 121, 121, 122, 122,
|
|
122, 122, 122, 122, 122, 123, 123, 123,
|
|
123, 123, 123, 123, 124, 124, 124, 124,
|
|
124, 124, 124, 125, 125, 125, 125, 125,
|
|
125, 125, 126, 126, 126, 126, 126, 126,
|
|
126, 127, 127, 127, 127, 127, 127, 127,
|
|
128, 128, 128, 128, 128, 128, 128, 129,
|
|
129, 129, 129, 129, 129, 129, 130, 130,
|
|
130, 130, 130, 130, 130, 131, 131, 131,
|
|
131, 131, 131, 131, 132, 132, 132, 132,
|
|
132, 132, 132, 133, 133, 133, 133, 133,
|
|
133, 133, 134, 134, 134, 134, 134, 134,
|
|
134, 135, 135, 135, 135, 135, 135, 135,
|
|
136, 136, 136, 136, 136, 136, 136, 137,
|
|
137, 137, 137, 137, 137, 137, 138, 138,
|
|
138, 138, 138, 138, 138, 139, 139, 139,
|
|
139, 139, 139, 139, 140, 140, 140, 140,
|
|
140, 140, 140, 141, 141, 141, 141, 141,
|
|
141, 141, 142, 142, 142, 142, 142, 142,
|
|
142, 143, 143, 143, 143, 143, 143, 143,
|
|
144, 144, 144, 144, 144, 144, 144, 145,
|
|
145, 145, 145, 145, 145, 145, 146, 146,
|
|
146, 146, 146, 146, 146, 147, 147, 147,
|
|
147, 147, 147, 147, 148, 148, 148, 148,
|
|
148, 148, 148, 149, 149, 149, 149, 149,
|
|
149, 149, 150, 150, 150, 150, 150, 150,
|
|
150, 151, 151, 151, 151, 151, 151, 151,
|
|
152, 152, 152, 152, 152, 152, 152, 153,
|
|
153, 153, 153, 153, 153, 153, 154, 154,
|
|
154, 154, 154, 154, 154, 155, 155, 155,
|
|
155, 155, 155, 155, 156, 156, 156, 156,
|
|
156, 156, 156, 157, 157, 157, 157, 157,
|
|
157, 157, 158, 158, 158, 158, 158, 158,
|
|
158, 159, 159, 159, 159, 159, 159, 159,
|
|
160, 160, 160, 160, 160, 160, 160, 161,
|
|
161, 161, 161, 161, 161, 161, 162, 162,
|
|
162, 162, 162, 162, 162, 163, 163, 163,
|
|
163, 163, 163, 163, 164, 164, 164, 164,
|
|
164, 164, 164, 165, 165, 165, 165, 165,
|
|
165, 165, 166, 166, 166, 166, 166, 166,
|
|
166, 167, 167, 167, 167, 167, 167, 167,
|
|
168, 168, 168, 168, 168, 168, 168, 169,
|
|
169, 169, 169, 169, 169, 169, 170, 170,
|
|
170, 170, 170, 170, 170, 171, 171, 171,
|
|
171, 171, 171, 171, 172, 172, 172, 172,
|
|
172, 172, 172, 173, 173, 173, 173, 173,
|
|
173, 173, 174, 174, 174, 174, 174, 174,
|
|
174, 175, 175, 175, 175, 175, 175, 175,
|
|
176, 176, 176, 176, 176, 176, 176, 177,
|
|
177, 177, 177, 177, 177, 177, 178, 178,
|
|
178, 178, 178, 178, 178, 179, 179, 179,
|
|
179, 179, 179, 179, 180, 180, 180, 180,
|
|
180, 180, 180, 181, 181, 181, 181, 181,
|
|
181, 181, 182, 182, 182, 182, 182, 182,
|
|
182, 183, 183, 183, 183, 183, 183, 183,
|
|
184, 184, 184, 184, 184, 184, 184, 185,
|
|
185, 185, 185, 185, 185, 185, 186, 186,
|
|
186, 186, 186, 186, 186, 187, 187, 187,
|
|
187, 187, 187, 187, 188, 188, 188, 188,
|
|
188, 188, 188, 189, 189, 189, 189, 189,
|
|
189, 189, 190, 190, 190, 190, 190, 190,
|
|
190, 191, 191, 191, 191, 191, 191, 191,
|
|
192, 192, 192, 192, 192, 192, 192, 193,
|
|
193, 193, 193, 193, 193, 193, 194, 194,
|
|
194, 194, 194, 194, 194, 195, 195, 195,
|
|
195, 195, 195, 195, 196, 196, 196, 196,
|
|
196, 196, 196, 197, 197, 197, 197, 197,
|
|
197, 197, 198, 198, 198, 198, 198, 198,
|
|
198, 199, 199, 199, 199, 199, 199, 199,
|
|
200, 200, 200, 200, 200, 200, 200, 201,
|
|
201, 201, 201, 201, 201, 201, 202, 202,
|
|
202, 202, 202, 202, 202, 203, 203, 203,
|
|
203, 203, 203, 203, 204, 204, 204, 204,
|
|
204, 204, 204, 205, 205, 205, 205, 205,
|
|
205, 205, 206, 206, 206, 206, 206, 206,
|
|
206, 207, 207, 207, 207, 207, 207, 207,
|
|
208, 208, 208, 208, 208, 208, 208, 209,
|
|
209, 209, 209, 209, 209, 209, 210, 210,
|
|
210, 210, 210, 210, 210, 211, 211, 211,
|
|
211, 211, 211, 211, 212, 212, 212, 212,
|
|
212, 212, 212, 213, 213, 213, 213, 213,
|
|
213, 213, 214, 214, 214, 214, 214, 214,
|
|
214, 215, 215, 215, 215, 215, 215, 215,
|
|
216, 216, 216, 216, 216, 216, 216, 217,
|
|
217, 217, 217, 217, 217, 217, 218, 218,
|
|
218, 218, 218, 218, 218, 219, 219, 219,
|
|
219, 219, 219, 219, 220, 220, 220, 220,
|
|
220, 220, 220, 221, 221, 221, 221, 221,
|
|
221, 221, 222, 222, 222, 222, 222, 222,
|
|
222, 223, 223, 223, 223, 223, 223, 223,
|
|
224, 224, 224, 224, 224, 224, 224, 225,
|
|
225, 225, 225, 225, 225, 225, 226, 226,
|
|
226, 226, 226, 226, 226, 227, 227, 227,
|
|
227, 227, 227, 227, 228, 228, 228, 228,
|
|
228, 228, 228, 229, 229, 229, 229, 229,
|
|
229, 229, 230, 230, 230, 230, 230, 230,
|
|
230, 231, 231, 231, 231, 231, 231, 231,
|
|
232, 232, 232, 232, 232, 232, 232, 233,
|
|
233, 233, 233, 233, 233, 233, 234, 234,
|
|
234, 234, 234, 234, 234, 235, 235, 235,
|
|
235, 235, 235, 235, 236, 236, 236, 236,
|
|
236, 236, 236, 237, 237, 237, 237, 237,
|
|
237, 237, 238, 238, 238, 238, 238, 238,
|
|
238, 239, 239, 239, 239, 239, 239, 239,
|
|
240, 240, 240, 240, 240, 240, 240, 241,
|
|
241, 241, 241, 241, 241, 241, 242, 242,
|
|
242, 242, 242, 242, 242, 243, 243, 243,
|
|
243, 243, 243, 243, 244, 244, 244, 244,
|
|
244, 244, 244, 245, 245, 245, 245, 245,
|
|
245, 245, 246, 246, 246, 246, 246, 246,
|
|
246, 247, 247, 247, 247, 247, 247, 247,
|
|
248, 248, 248, 248, 248, 248, 248, 249,
|
|
249, 249, 249, 249, 249, 249, 250, 250,
|
|
250, 250, 250, 250, 250, 251, 251, 251,
|
|
251, 251, 251, 251, 252, 252, 252, 252,
|
|
252, 252, 252, 253, 253, 253, 253, 253,
|
|
253, 253, 254, 254, 254, 254, 254, 254,
|
|
254, 255, 255, 255, 255, 255, 255, 255,
|
|
};
|
|
|
|
const uint8_t detex_division_by_5_table[1280] =
|
|
{
|
|
0, 0, 0, 0, 0, 1, 1, 1,
|
|
1, 1, 2, 2, 2, 2, 2, 3,
|
|
3, 3, 3, 3, 4, 4, 4, 4,
|
|
4, 5, 5, 5, 5, 5, 6, 6,
|
|
6, 6, 6, 7, 7, 7, 7, 7,
|
|
8, 8, 8, 8, 8, 9, 9, 9,
|
|
9, 9, 10, 10, 10, 10, 10, 11,
|
|
11, 11, 11, 11, 12, 12, 12, 12,
|
|
12, 13, 13, 13, 13, 13, 14, 14,
|
|
14, 14, 14, 15, 15, 15, 15, 15,
|
|
16, 16, 16, 16, 16, 17, 17, 17,
|
|
17, 17, 18, 18, 18, 18, 18, 19,
|
|
19, 19, 19, 19, 20, 20, 20, 20,
|
|
20, 21, 21, 21, 21, 21, 22, 22,
|
|
22, 22, 22, 23, 23, 23, 23, 23,
|
|
24, 24, 24, 24, 24, 25, 25, 25,
|
|
25, 25, 26, 26, 26, 26, 26, 27,
|
|
27, 27, 27, 27, 28, 28, 28, 28,
|
|
28, 29, 29, 29, 29, 29, 30, 30,
|
|
30, 30, 30, 31, 31, 31, 31, 31,
|
|
32, 32, 32, 32, 32, 33, 33, 33,
|
|
33, 33, 34, 34, 34, 34, 34, 35,
|
|
35, 35, 35, 35, 36, 36, 36, 36,
|
|
36, 37, 37, 37, 37, 37, 38, 38,
|
|
38, 38, 38, 39, 39, 39, 39, 39,
|
|
40, 40, 40, 40, 40, 41, 41, 41,
|
|
41, 41, 42, 42, 42, 42, 42, 43,
|
|
43, 43, 43, 43, 44, 44, 44, 44,
|
|
44, 45, 45, 45, 45, 45, 46, 46,
|
|
46, 46, 46, 47, 47, 47, 47, 47,
|
|
48, 48, 48, 48, 48, 49, 49, 49,
|
|
49, 49, 50, 50, 50, 50, 50, 51,
|
|
51, 51, 51, 51, 52, 52, 52, 52,
|
|
52, 53, 53, 53, 53, 53, 54, 54,
|
|
54, 54, 54, 55, 55, 55, 55, 55,
|
|
56, 56, 56, 56, 56, 57, 57, 57,
|
|
57, 57, 58, 58, 58, 58, 58, 59,
|
|
59, 59, 59, 59, 60, 60, 60, 60,
|
|
60, 61, 61, 61, 61, 61, 62, 62,
|
|
62, 62, 62, 63, 63, 63, 63, 63,
|
|
64, 64, 64, 64, 64, 65, 65, 65,
|
|
65, 65, 66, 66, 66, 66, 66, 67,
|
|
67, 67, 67, 67, 68, 68, 68, 68,
|
|
68, 69, 69, 69, 69, 69, 70, 70,
|
|
70, 70, 70, 71, 71, 71, 71, 71,
|
|
72, 72, 72, 72, 72, 73, 73, 73,
|
|
73, 73, 74, 74, 74, 74, 74, 75,
|
|
75, 75, 75, 75, 76, 76, 76, 76,
|
|
76, 77, 77, 77, 77, 77, 78, 78,
|
|
78, 78, 78, 79, 79, 79, 79, 79,
|
|
80, 80, 80, 80, 80, 81, 81, 81,
|
|
81, 81, 82, 82, 82, 82, 82, 83,
|
|
83, 83, 83, 83, 84, 84, 84, 84,
|
|
84, 85, 85, 85, 85, 85, 86, 86,
|
|
86, 86, 86, 87, 87, 87, 87, 87,
|
|
88, 88, 88, 88, 88, 89, 89, 89,
|
|
89, 89, 90, 90, 90, 90, 90, 91,
|
|
91, 91, 91, 91, 92, 92, 92, 92,
|
|
92, 93, 93, 93, 93, 93, 94, 94,
|
|
94, 94, 94, 95, 95, 95, 95, 95,
|
|
96, 96, 96, 96, 96, 97, 97, 97,
|
|
97, 97, 98, 98, 98, 98, 98, 99,
|
|
99, 99, 99, 99, 100, 100, 100, 100,
|
|
100, 101, 101, 101, 101, 101, 102, 102,
|
|
102, 102, 102, 103, 103, 103, 103, 103,
|
|
104, 104, 104, 104, 104, 105, 105, 105,
|
|
105, 105, 106, 106, 106, 106, 106, 107,
|
|
107, 107, 107, 107, 108, 108, 108, 108,
|
|
108, 109, 109, 109, 109, 109, 110, 110,
|
|
110, 110, 110, 111, 111, 111, 111, 111,
|
|
112, 112, 112, 112, 112, 113, 113, 113,
|
|
113, 113, 114, 114, 114, 114, 114, 115,
|
|
115, 115, 115, 115, 116, 116, 116, 116,
|
|
116, 117, 117, 117, 117, 117, 118, 118,
|
|
118, 118, 118, 119, 119, 119, 119, 119,
|
|
120, 120, 120, 120, 120, 121, 121, 121,
|
|
121, 121, 122, 122, 122, 122, 122, 123,
|
|
123, 123, 123, 123, 124, 124, 124, 124,
|
|
124, 125, 125, 125, 125, 125, 126, 126,
|
|
126, 126, 126, 127, 127, 127, 127, 127,
|
|
128, 128, 128, 128, 128, 129, 129, 129,
|
|
129, 129, 130, 130, 130, 130, 130, 131,
|
|
131, 131, 131, 131, 132, 132, 132, 132,
|
|
132, 133, 133, 133, 133, 133, 134, 134,
|
|
134, 134, 134, 135, 135, 135, 135, 135,
|
|
136, 136, 136, 136, 136, 137, 137, 137,
|
|
137, 137, 138, 138, 138, 138, 138, 139,
|
|
139, 139, 139, 139, 140, 140, 140, 140,
|
|
140, 141, 141, 141, 141, 141, 142, 142,
|
|
142, 142, 142, 143, 143, 143, 143, 143,
|
|
144, 144, 144, 144, 144, 145, 145, 145,
|
|
145, 145, 146, 146, 146, 146, 146, 147,
|
|
147, 147, 147, 147, 148, 148, 148, 148,
|
|
148, 149, 149, 149, 149, 149, 150, 150,
|
|
150, 150, 150, 151, 151, 151, 151, 151,
|
|
152, 152, 152, 152, 152, 153, 153, 153,
|
|
153, 153, 154, 154, 154, 154, 154, 155,
|
|
155, 155, 155, 155, 156, 156, 156, 156,
|
|
156, 157, 157, 157, 157, 157, 158, 158,
|
|
158, 158, 158, 159, 159, 159, 159, 159,
|
|
160, 160, 160, 160, 160, 161, 161, 161,
|
|
161, 161, 162, 162, 162, 162, 162, 163,
|
|
163, 163, 163, 163, 164, 164, 164, 164,
|
|
164, 165, 165, 165, 165, 165, 166, 166,
|
|
166, 166, 166, 167, 167, 167, 167, 167,
|
|
168, 168, 168, 168, 168, 169, 169, 169,
|
|
169, 169, 170, 170, 170, 170, 170, 171,
|
|
171, 171, 171, 171, 172, 172, 172, 172,
|
|
172, 173, 173, 173, 173, 173, 174, 174,
|
|
174, 174, 174, 175, 175, 175, 175, 175,
|
|
176, 176, 176, 176, 176, 177, 177, 177,
|
|
177, 177, 178, 178, 178, 178, 178, 179,
|
|
179, 179, 179, 179, 180, 180, 180, 180,
|
|
180, 181, 181, 181, 181, 181, 182, 182,
|
|
182, 182, 182, 183, 183, 183, 183, 183,
|
|
184, 184, 184, 184, 184, 185, 185, 185,
|
|
185, 185, 186, 186, 186, 186, 186, 187,
|
|
187, 187, 187, 187, 188, 188, 188, 188,
|
|
188, 189, 189, 189, 189, 189, 190, 190,
|
|
190, 190, 190, 191, 191, 191, 191, 191,
|
|
192, 192, 192, 192, 192, 193, 193, 193,
|
|
193, 193, 194, 194, 194, 194, 194, 195,
|
|
195, 195, 195, 195, 196, 196, 196, 196,
|
|
196, 197, 197, 197, 197, 197, 198, 198,
|
|
198, 198, 198, 199, 199, 199, 199, 199,
|
|
200, 200, 200, 200, 200, 201, 201, 201,
|
|
201, 201, 202, 202, 202, 202, 202, 203,
|
|
203, 203, 203, 203, 204, 204, 204, 204,
|
|
204, 205, 205, 205, 205, 205, 206, 206,
|
|
206, 206, 206, 207, 207, 207, 207, 207,
|
|
208, 208, 208, 208, 208, 209, 209, 209,
|
|
209, 209, 210, 210, 210, 210, 210, 211,
|
|
211, 211, 211, 211, 212, 212, 212, 212,
|
|
212, 213, 213, 213, 213, 213, 214, 214,
|
|
214, 214, 214, 215, 215, 215, 215, 215,
|
|
216, 216, 216, 216, 216, 217, 217, 217,
|
|
217, 217, 218, 218, 218, 218, 218, 219,
|
|
219, 219, 219, 219, 220, 220, 220, 220,
|
|
220, 221, 221, 221, 221, 221, 222, 222,
|
|
222, 222, 222, 223, 223, 223, 223, 223,
|
|
224, 224, 224, 224, 224, 225, 225, 225,
|
|
225, 225, 226, 226, 226, 226, 226, 227,
|
|
227, 227, 227, 227, 228, 228, 228, 228,
|
|
228, 229, 229, 229, 229, 229, 230, 230,
|
|
230, 230, 230, 231, 231, 231, 231, 231,
|
|
232, 232, 232, 232, 232, 233, 233, 233,
|
|
233, 233, 234, 234, 234, 234, 234, 235,
|
|
235, 235, 235, 235, 236, 236, 236, 236,
|
|
236, 237, 237, 237, 237, 237, 238, 238,
|
|
238, 238, 238, 239, 239, 239, 239, 239,
|
|
240, 240, 240, 240, 240, 241, 241, 241,
|
|
241, 241, 242, 242, 242, 242, 242, 243,
|
|
243, 243, 243, 243, 244, 244, 244, 244,
|
|
244, 245, 245, 245, 245, 245, 246, 246,
|
|
246, 246, 246, 247, 247, 247, 247, 247,
|
|
248, 248, 248, 248, 248, 249, 249, 249,
|
|
249, 249, 250, 250, 250, 250, 250, 251,
|
|
251, 251, 251, 251, 252, 252, 252, 252,
|
|
252, 253, 253, 253, 253, 253, 254, 254,
|
|
254, 254, 254, 255, 255, 255, 255, 255,
|
|
};
|
|
|
|
const uint8_t detex_clamp0to255_table[255 + 256 + 256] =
|
|
{
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32,
|
|
33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
|
|
49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64,
|
|
65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80,
|
|
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96,
|
|
97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112,
|
|
113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 128,
|
|
129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140, 141, 142, 143, 144,
|
|
145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
|
|
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176,
|
|
177, 178, 179, 180, 181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192,
|
|
193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, 204, 205, 206, 207, 208,
|
|
209, 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, 222, 223, 224,
|
|
225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, 240,
|
|
241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255
|
|
};
|
|
|
|
typedef bool (*detexDecompressBlockFuncType)(const uint8_t *bitstring, uint32_t mode_mask, uint32_t flags, uint8_t *pixel_buffer);
|
|
|
|
/**
|
|
*/
|
|
typedef struct
|
|
{
|
|
uint32_t format;
|
|
uint8_t *data;
|
|
int width;
|
|
int height;
|
|
int width_in_blocks;
|
|
int height_in_blocks;
|
|
} FDetexTexture;
|
|
|
|
/** Data structure used to extract bits from 128-bit bitstring. */
|
|
typedef struct
|
|
{
|
|
uint64_t data0;
|
|
uint64_t data1;
|
|
int index;
|
|
} FDetexBlock128;
|
|
|
|
static int detexMatchConversion(uint32_t source_pixel_format, uint32_t target_pixel_format, uint32_t *conversion);
|
|
|
|
uint32_t detexBlock128ExtractBits(FDetexBlock128 *block, int nu_bits)
|
|
{
|
|
uint32_t value = 0;
|
|
for (int i = 0; i < nu_bits; i++)
|
|
{
|
|
if (block->index < 64)
|
|
{
|
|
int shift = block->index - i;
|
|
if (shift < 0)
|
|
value |= (block->data0 & ((uint64_t)1 << block->index)) << (-shift);
|
|
else
|
|
value |= (block->data0 & ((uint64_t)1 << block->index)) >> shift;
|
|
}
|
|
else
|
|
{
|
|
int shift = ((block->index - 64) - i);
|
|
if (shift < 0)
|
|
value |= (block->data1 & ((uint64_t)1 << (block->index - 64))) << (-shift);
|
|
else
|
|
value |= (block->data1 & ((uint64_t)1 << (block->index - 64))) >> shift;
|
|
}
|
|
block->index++;
|
|
}
|
|
// if (block->index > 128)
|
|
// printf("Block overflow (%d)\n", block->index);
|
|
return value;
|
|
}
|
|
|
|
/** Return the compressed texture type index of a texture format. */
|
|
static DETEX_INLINE_ONLY uint32_t detexGetCompressedFormat(uint32_t texture_format)
|
|
{
|
|
return texture_format >> 24;
|
|
}
|
|
|
|
/** Return the block size of a compressed texture format in bytes. */
|
|
static DETEX_INLINE_ONLY uint32_t detexGetCompressedBlockSize(uint32_t texture_format)
|
|
{
|
|
return 8 + ((texture_format & DETEX_TEXTURE_FORMAT_128BIT_BLOCK_BIT) >> 20);
|
|
}
|
|
|
|
/* Return the pixel format of a texture format. */
|
|
static DETEX_INLINE_ONLY uint32_t detexGetPixelFormat(uint32_t texture_format)
|
|
{
|
|
return texture_format & DETEX_TEXTURE_FORMAT_PIXEL_FORMAT_MASK;
|
|
}
|
|
|
|
/* Integer division using look-up tables, used by BC1/2/3 and RGTC (BC4/5) */
|
|
/* decompression. */
|
|
|
|
static DETEX_INLINE_ONLY uint32_t detexDivide0To767By3(uint32_t value)
|
|
{
|
|
return detex_division_by_3_table[value];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY uint32_t detexDivide0To1791By7(uint32_t value)
|
|
{
|
|
return detex_division_by_7_table[value];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int8_t detexSignInt32(int v)
|
|
{
|
|
return (int8_t)((v >> 31) | -(-v >> 31));
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int detexDivideMinus895To895By7(int value)
|
|
{
|
|
return (int8_t)detex_division_by_7_table[abs(value)] * detexSignInt32(value);
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY uint32_t detexDivide0To1279By5(uint32_t value)
|
|
{
|
|
return detex_division_by_5_table[value];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int detexDivideMinus639To639By5(int value)
|
|
{
|
|
return (int8_t)detex_division_by_5_table[abs(value)] * detexSignInt32(value);
|
|
}
|
|
|
|
/** Return bitfield from bit0 to bit1 from 64-bit bitstring. */
|
|
static DETEX_INLINE_ONLY uint32_t detexGetBits64(uint64_t data, int bit0, int bit1)
|
|
{
|
|
return (data & (((uint64_t)1 << (bit1 + 1)) - 1)) >> bit0;
|
|
}
|
|
|
|
/** Return reversed bitfield (bit1 to bit0) from 64-bit bitstring. */
|
|
static DETEX_INLINE_ONLY uint32_t detexGetBits64Reversed(uint64_t data, int bit0, int bit1)
|
|
{
|
|
// Assumes bit0 > bit1.
|
|
// Reverse the bits.
|
|
uint32_t val = 0;
|
|
for (int i = 0; i <= bit0 - bit1; i++)
|
|
{
|
|
int shift_right = bit0 - 2 * i;
|
|
if (shift_right >= 0)
|
|
val |= (data & ((uint64_t)1 << (bit0 - i))) >> shift_right;
|
|
else
|
|
val |= (data & ((uint64_t)1 << (bit0 - i))) << (-shift_right);
|
|
}
|
|
return val;
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the BC1 format. */
|
|
bool detexDecompressBlockBC1(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__)
|
|
uint32_t colors = *(uint32_t *)&bitstring[0];
|
|
#else
|
|
uint32_t colors = ((uint32_t)bitstring[0] << 24) |
|
|
((uint32_t)bitstring[1] << 16) |
|
|
((uint32_t)bitstring[2] << 8) | bitstring[3];
|
|
#endif
|
|
// Decode the two 5-6-5 RGB colors.
|
|
int color_r[4], color_g[4], color_b[4];
|
|
color_b[0] = (colors & 0x0000001F) << 3;
|
|
color_g[0] = (colors & 0x000007E0) >> (5 - 2);
|
|
color_r[0] = (colors & 0x0000F800) >> (11 - 3);
|
|
color_b[1] = (colors & 0x001F0000) >> (16 - 3);
|
|
color_g[1] = (colors & 0x07E00000) >> (21 - 2);
|
|
color_r[1] = (colors & 0xF8000000) >> (27 - 3);
|
|
if ((colors & 0xFFFF) > ((colors & 0xFFFF0000) >> 16))
|
|
{
|
|
color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]);
|
|
color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]);
|
|
color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]);
|
|
color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]);
|
|
color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]);
|
|
color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]);
|
|
}
|
|
else
|
|
{
|
|
color_r[2] = (color_r[0] + color_r[1]) / 2;
|
|
color_g[2] = (color_g[0] + color_g[1]) / 2;
|
|
color_b[2] = (color_b[0] + color_b[1]) / 2;
|
|
color_r[3] = color_g[3] = color_b[3] = 0;
|
|
}
|
|
uint32_t pixels = *(uint32_t *)&bitstring[4];
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel = (pixels >> (i * 2)) & 0x3;
|
|
*(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGB8Alpha0xFF(color_r[pixel], color_g[pixel], color_b[pixel]);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
uint32_t detexGetModeBC1(const uint8_t *bitstring)
|
|
{
|
|
uint32_t colors = *(uint32_t *)bitstring;
|
|
if ((colors & 0xFFFF) > ((colors & 0xFFFF0000) >> 16))
|
|
return 0;
|
|
else
|
|
return 1;
|
|
}
|
|
|
|
void detexSetModeBC1(uint8_t *bitstring, uint32_t mode, uint32_t flags, uint32_t *colors)
|
|
{
|
|
uint32_t colorbits = *(uint32_t *)bitstring;
|
|
uint32_t current_mode;
|
|
if ((colorbits & 0xFFFF) > ((colorbits & 0xFFFF0000) >> 16))
|
|
current_mode = 0;
|
|
else
|
|
current_mode = 1;
|
|
if (current_mode != mode)
|
|
{
|
|
colorbits = ((colorbits & 0xFFFF) << 16) | (colorbits >> 16);
|
|
*(uint32_t *)bitstring = colorbits;
|
|
}
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the BC1A format. */
|
|
bool detexDecompressBlockBC1A(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__)
|
|
uint32_t colors = *(uint32_t *)&bitstring[0];
|
|
#else
|
|
uint32_t colors = ((uint32_t)bitstring[0] << 24) |
|
|
((uint32_t)bitstring[1] << 16) |
|
|
((uint32_t)bitstring[2] << 8) | bitstring[3];
|
|
#endif
|
|
bool opaque = ((colors & 0xFFFF) > ((colors & 0xFFFF0000) >> 16));
|
|
if (opaque && (flags & DETEX_DECOMPRESS_FLAG_NON_OPAQUE_ONLY))
|
|
return false;
|
|
if (!opaque && (flags & DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY))
|
|
return false;
|
|
// Decode the two 5-6-5 RGB colors.
|
|
int color_r[4], color_g[4], color_b[4], color_a[4];
|
|
color_b[0] = (colors & 0x0000001F) << 3;
|
|
color_g[0] = (colors & 0x000007E0) >> (5 - 2);
|
|
color_r[0] = (colors & 0x0000F800) >> (11 - 3);
|
|
color_b[1] = (colors & 0x001F0000) >> (16 - 3);
|
|
color_g[1] = (colors & 0x07E00000) >> (21 - 2);
|
|
color_r[1] = (colors & 0xF8000000) >> (27 - 3);
|
|
color_a[0] = color_a[1] = color_a[2] = color_a[3] = 0xFF;
|
|
if (opaque)
|
|
{
|
|
color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]);
|
|
color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]);
|
|
color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]);
|
|
color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]);
|
|
color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]);
|
|
color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]);
|
|
}
|
|
else
|
|
{
|
|
color_r[2] = (color_r[0] + color_r[1]) / 2;
|
|
color_g[2] = (color_g[0] + color_g[1]) / 2;
|
|
color_b[2] = (color_b[0] + color_b[1]) / 2;
|
|
color_r[3] = color_g[3] = color_b[3] = color_a[3] = 0;
|
|
}
|
|
uint32_t pixels = *(uint32_t *)&bitstring[4];
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel = (pixels >> (i * 2)) & 0x3;
|
|
*(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGBA8(color_r[pixel], color_g[pixel], color_b[pixel], color_a[pixel]);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the BC2 format. */
|
|
bool detexDecompressBlockBC2(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__)
|
|
uint32_t colors = *(uint32_t *)&bitstring[8];
|
|
#else
|
|
uint32_t colors = ((uint32_t)bitstring[8] << 24) |
|
|
((uint32_t)bitstring[9] << 16) |
|
|
((uint32_t)bitstring[10] << 8) | bitstring[11];
|
|
#endif
|
|
if ((colors & 0xFFFF) <= ((colors & 0xFFFF0000) >> 16) &&
|
|
(flags & DETEX_DECOMPRESS_FLAG_ENCODE))
|
|
// GeForce 6 and 7 series produce wrong result in this case.
|
|
return false;
|
|
int color_r[4], color_g[4], color_b[4];
|
|
color_b[0] = (colors & 0x0000001F) << 3;
|
|
color_g[0] = (colors & 0x000007E0) >> (5 - 2);
|
|
color_r[0] = (colors & 0x0000F800) >> (11 - 3);
|
|
color_b[1] = (colors & 0x001F0000) >> (16 - 3);
|
|
color_g[1] = (colors & 0x07E00000) >> (21 - 2);
|
|
color_r[1] = (colors & 0xF8000000) >> (27 - 3);
|
|
color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]);
|
|
color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]);
|
|
color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]);
|
|
color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]);
|
|
color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]);
|
|
color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]);
|
|
uint32_t pixels = *(uint32_t *)&bitstring[12];
|
|
uint64_t alpha_pixels = *(uint64_t *)&bitstring[0];
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel = (pixels >> (i * 2)) & 0x3;
|
|
int alpha = ((alpha_pixels >> (i * 4)) & 0xF) * 255 / 15;
|
|
*(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGBA8(color_r[pixel], color_g[pixel], color_b[pixel], alpha);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the BC3 format. */
|
|
bool detexDecompressBlockBC3(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int alpha0 = bitstring[0];
|
|
int alpha1 = bitstring[1];
|
|
if (alpha0 > alpha1 && (flags & DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY))
|
|
return false;
|
|
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ || !defined(__BYTE_ORDER__)
|
|
uint32_t colors = *(uint32_t *)&bitstring[8];
|
|
#else
|
|
uint32_t colors = ((uint32_t)bitstring[8] << 24) |
|
|
((uint32_t)bitstring[9] << 16) |
|
|
((uint32_t)bitstring[10] << 8) | bitstring[11];
|
|
#endif
|
|
if ((colors & 0xFFFF) <= ((colors & 0xFFFF0000) >> 16) &&
|
|
(flags & DETEX_DECOMPRESS_FLAG_ENCODE))
|
|
// GeForce 6 and 7 series produce wrong result in this case.
|
|
return false;
|
|
int color_r[4], color_g[4], color_b[4];
|
|
// color_x[] has a value between 0 and 248 with the lower three bits zero.
|
|
color_b[0] = (colors & 0x0000001F) << 3;
|
|
color_g[0] = (colors & 0x000007E0) >> (5 - 2);
|
|
color_r[0] = (colors & 0x0000F800) >> (11 - 3);
|
|
color_b[1] = (colors & 0x001F0000) >> (16 - 3);
|
|
color_g[1] = (colors & 0x07E00000) >> (21 - 2);
|
|
color_r[1] = (colors & 0xF8000000) >> (27 - 3);
|
|
color_r[2] = detexDivide0To767By3(2 * color_r[0] + color_r[1]);
|
|
color_g[2] = detexDivide0To767By3(2 * color_g[0] + color_g[1]);
|
|
color_b[2] = detexDivide0To767By3(2 * color_b[0] + color_b[1]);
|
|
color_r[3] = detexDivide0To767By3(color_r[0] + 2 * color_r[1]);
|
|
color_g[3] = detexDivide0To767By3(color_g[0] + 2 * color_g[1]);
|
|
color_b[3] = detexDivide0To767By3(color_b[0] + 2 * color_b[1]);
|
|
uint32_t pixels = *(uint32_t *)&bitstring[12];
|
|
uint64_t alpha_bits = (uint32_t)bitstring[2] | ((uint32_t)bitstring[3] << 8) | ((uint64_t)*(uint32_t *)&bitstring[4] << 16);
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel = (pixels >> (i * 2)) & 0x3;
|
|
int code = (alpha_bits >> (i * 3)) & 0x7;
|
|
int alpha;
|
|
if (alpha0 > alpha1)
|
|
{
|
|
switch (code)
|
|
{
|
|
case 0 : alpha = alpha0; break;
|
|
case 1 : alpha = alpha1; break;
|
|
case 2 : alpha = detexDivide0To1791By7(6 * alpha0 + 1 * alpha1); break;
|
|
case 3 : alpha = detexDivide0To1791By7(5 * alpha0 + 2 * alpha1); break;
|
|
case 4 : alpha = detexDivide0To1791By7(4 * alpha0 + 3 * alpha1); break;
|
|
case 5 : alpha = detexDivide0To1791By7(3 * alpha0 + 4 * alpha1); break;
|
|
case 6 : alpha = detexDivide0To1791By7(2 * alpha0 + 5 * alpha1); break;
|
|
case 7 : alpha = detexDivide0To1791By7(1 * alpha0 + 6 * alpha1); break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (code)
|
|
{
|
|
case 0 : alpha = alpha0; break;
|
|
case 1 : alpha = alpha1; break;
|
|
case 2 : alpha = detexDivide0To1279By5(4 * alpha0 + 1 * alpha1); break;
|
|
case 3 : alpha = detexDivide0To1279By5(3 * alpha0 + 2 * alpha1); break;
|
|
case 4 : alpha = detexDivide0To1279By5(2 * alpha0 + 3 * alpha1); break;
|
|
case 5 : alpha = detexDivide0To1279By5(1 * alpha0 + 4 * alpha1); break;
|
|
case 6 : alpha = 0; break;
|
|
case 7 : alpha = 0xFF; break;
|
|
}
|
|
}
|
|
*(uint32_t *)(pixel_buffer + i * 4) = detexPack32RGBA8(color_r[pixel], color_g[pixel], color_b[pixel], alpha);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
For each pixel, decode an 8-bit integer and store as follows:
|
|
If shift and offset are zero, store each value in consecutive 8 bit values in pixel_buffer.
|
|
If shift is one, store each value in consecutive 16-bit words in pixel_buffer; if offset
|
|
is zero, store it in the first 8 bits, if offset is one store it in the last 8 bits of each
|
|
16-bit word.
|
|
*/
|
|
static DETEX_INLINE_ONLY void DecodeBlockRGTC(const uint8_t * DETEX_RESTRICT bitstring, int shift, int offset, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
// LSBFirst byte order only.
|
|
uint64_t bits = (*(uint64_t *)&bitstring[0]) >> 16;
|
|
int lum0 = bitstring[0];
|
|
int lum1 = bitstring[1];
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int control_code = bits & 0x7;
|
|
uint8_t output;
|
|
if (lum0 > lum1)
|
|
{
|
|
switch (control_code)
|
|
{
|
|
case 0 : output = lum0; break;
|
|
case 1 : output = lum1; break;
|
|
case 2 : output = detexDivide0To1791By7(6 * lum0 + lum1); break;
|
|
case 3 : output = detexDivide0To1791By7(5 * lum0 + 2 * lum1); break;
|
|
case 4 : output = detexDivide0To1791By7(4 * lum0 + 3 * lum1); break;
|
|
case 5 : output = detexDivide0To1791By7(3 * lum0 + 4 * lum1); break;
|
|
case 6 : output = detexDivide0To1791By7(2 * lum0 + 5 * lum1); break;
|
|
case 7 : output = detexDivide0To1791By7(lum0 + 6 * lum1); break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (control_code)
|
|
{
|
|
case 0 : output = lum0; break;
|
|
case 1 : output = lum1; break;
|
|
case 2 : output = detexDivide0To1279By5(4 * lum0 + lum1); break;
|
|
case 3 : output = detexDivide0To1279By5(3 * lum0 + 2 * lum1); break;
|
|
case 4 : output = detexDivide0To1279By5(2 * lum0 + 3 * lum1); break;
|
|
case 5 : output = detexDivide0To1279By5(lum0 + 4 * lum1); break;
|
|
case 6 : output = 0; break;
|
|
case 7 : output = 0xFF; break;
|
|
}
|
|
}
|
|
pixel_buffer[(i << shift) + offset] = output;
|
|
bits >>= 3;
|
|
}
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the unsigned RGTC1 (BC4) format. */
|
|
bool detexDecompressBlockRGTC1(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
DecodeBlockRGTC(bitstring, 0, 0, pixel_buffer);
|
|
return true;
|
|
}
|
|
|
|
/** Decompress a 128-bit 4x4 pixel texture block compressed using the unsigned RGTC2 (BC5) format. */
|
|
bool detexDecompressBlockRGTC2(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
DecodeBlockRGTC(bitstring, 1, 0, pixel_buffer);
|
|
DecodeBlockRGTC(&bitstring[8], 1, 1, pixel_buffer);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
For each pixel, decode an 16-bit integer and store as follows:
|
|
If shift and offset are zero, store each value in consecutive 16 bit values in pixel_buffer.
|
|
If shift is one, store each value in consecutive 32-bit words in pixel_buffer; if offset
|
|
is zero, store it in the first 16 bits, if offset is one store it in the last 16 bits of each
|
|
32-bit word. Returns true if the compressed block is valid.
|
|
*/
|
|
static DETEX_INLINE_ONLY bool DecodeBlockSignedRGTC(const uint8_t * DETEX_RESTRICT bitstring, int shift, int offset, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
// LSBFirst byte order only.
|
|
uint64_t bits = (*(uint64_t *)&bitstring[0]) >> 16;
|
|
int lum0 = (int8_t)bitstring[0];
|
|
int lum1 = (int8_t)bitstring[1];
|
|
if (lum0 == - 127 && lum1 == - 128)
|
|
// Not allowed.
|
|
return false;
|
|
if (lum0 == - 128)
|
|
lum0 = - 127;
|
|
if (lum1 == - 128)
|
|
lum1 = - 127;
|
|
// Note: values are mapped to a red value of -127 to 127.
|
|
uint16_t *pixel16_buffer = (uint16_t *)pixel_buffer;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int control_code = bits & 0x7;
|
|
int32_t result;
|
|
if (lum0 > lum1)
|
|
{
|
|
switch (control_code)
|
|
{
|
|
case 0 : result = lum0; break;
|
|
case 1 : result = lum1; break;
|
|
case 2 : result = detexDivideMinus895To895By7(6 * lum0 + lum1); break;
|
|
case 3 : result = detexDivideMinus895To895By7(5 * lum0 + 2 * lum1); break;
|
|
case 4 : result = detexDivideMinus895To895By7(4 * lum0 + 3 * lum1); break;
|
|
case 5 : result = detexDivideMinus895To895By7(3 * lum0 + 4 * lum1); break;
|
|
case 6 : result = detexDivideMinus895To895By7(2 * lum0 + 5 * lum1); break;
|
|
case 7 : result = detexDivideMinus895To895By7(lum0 + 6 * lum1); break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (control_code)
|
|
{
|
|
case 0 : result = lum0; break;
|
|
case 1 : result = lum1; break;
|
|
case 2 : result = detexDivideMinus639To639By5(4 * lum0 + lum1); break;
|
|
case 3 : result = detexDivideMinus639To639By5(3 * lum0 + 2 * lum1); break;
|
|
case 4 : result = detexDivideMinus639To639By5(2 * lum0 + 3 * lum1); break;
|
|
case 5 : result = detexDivideMinus639To639By5(lum0 + 4 * lum1); break;
|
|
case 6 : result = - 127; break;
|
|
case 7 : result = 127; break;
|
|
}
|
|
}
|
|
// Map from [-127, 127] to [-32768, 32767].
|
|
pixel16_buffer[(i << shift) + offset] = (uint16_t)(int16_t)
|
|
((result + 127) * 65535 / 254 - 32768);
|
|
bits >>= 3;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the signed RGTC1 (signed BC4) format. */
|
|
bool detexDecompressBlockSIGNED_RGTC1(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
return DecodeBlockSignedRGTC(bitstring, 0, 0, pixel_buffer);
|
|
}
|
|
|
|
/** Decompress a 128-bit 4x4 pixel texture block compressed using the signed RGTC2 (signed BC5) format. */
|
|
bool detexDecompressBlockSIGNED_RGTC2(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
bool r = DecodeBlockSignedRGTC(bitstring, 1, 0, pixel_buffer);
|
|
if (!r)
|
|
return false;
|
|
return DecodeBlockSignedRGTC(&bitstring[8], 1, 1, pixel_buffer);
|
|
}
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////////////
|
|
static int ExtractMode(FDetexBlock128 *block)
|
|
{
|
|
uint32_t mode = detexBlock128ExtractBits(block, 2);
|
|
if (mode < 2)
|
|
return mode;
|
|
return map_mode_table[mode | (detexBlock128ExtractBits(block, 3) << 2)];
|
|
}
|
|
|
|
static int GetPartitionIndex(int nu_subsets, int partition_set_id, int i)
|
|
{
|
|
if (nu_subsets == 1)
|
|
return 0;
|
|
// nu_subset == 2
|
|
return detex_bptc_table_P2[partition_set_id * 16 + i];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int GetAnchorIndex(int partition_set_id, int partition, int nu_subsets)
|
|
{
|
|
if (partition == 0)
|
|
return 0;
|
|
// nu_subsets = 2, partition = 1.
|
|
return detex_bptc_table_anchor_index_second_subset[partition_set_id];
|
|
}
|
|
|
|
static uint32_t Unquantize(uint16_t x, int mode)
|
|
{
|
|
int32_t unq;
|
|
if (mode == 13)
|
|
unq = x;
|
|
else if (x == 0)
|
|
unq = 0;
|
|
else if (x == (((int32_t)1 << bptc_float_EPB[mode]) - 1))
|
|
unq = 0xFFFF;
|
|
else
|
|
unq = (((int32_t)x << 15) + 0x4000) >> (bptc_float_EPB[mode] - 1);
|
|
return unq;
|
|
}
|
|
|
|
static int32_t UnquantizeSigned(int16_t x, int mode)
|
|
{
|
|
int s = 0;
|
|
int32_t unq;
|
|
if (bptc_float_EPB[mode] >= 16)
|
|
unq = x;
|
|
else
|
|
{
|
|
if (x < 0) {
|
|
s = 1;
|
|
x = -x;
|
|
}
|
|
if (x == 0)
|
|
unq = 0;
|
|
else
|
|
if (x >= (((int32_t)1 << (bptc_float_EPB[mode] - 1)) - 1))
|
|
unq = 0x7FFF;
|
|
else
|
|
unq = (((int32_t)x << 15) + 0x4000) >> (bptc_float_EPB[mode] - 1);
|
|
if (s)
|
|
unq = -unq;
|
|
}
|
|
return unq;
|
|
}
|
|
|
|
static int SignExtend(int value, int source_nu_bits, int target_nu_bits)
|
|
{
|
|
uint32_t sign_bit = value & (1 << (source_nu_bits - 1));
|
|
if (!sign_bit)
|
|
return value;
|
|
uint32_t sign_extend_bits = 0xFFFFFFFF ^ ((1 << source_nu_bits) - 1);
|
|
sign_extend_bits &= ((uint64_t)1 << target_nu_bits) - 1;
|
|
return value | sign_extend_bits;
|
|
}
|
|
|
|
static int32_t InterpolateFloat(int32_t e0, int32_t e1, int16_t index, uint8_t indexprecision)
|
|
{
|
|
if (indexprecision == 2)
|
|
return (((64 - detex_bptc_table_aWeight2[index]) * e0 + detex_bptc_table_aWeight2[index] * e1 + 32) >> 6);
|
|
else if (indexprecision == 3)
|
|
return (((64 - detex_bptc_table_aWeight3[index]) * e0 + detex_bptc_table_aWeight3[index] * e1 + 32) >> 6);
|
|
else // indexprecision == 4
|
|
return (((64 - detex_bptc_table_aWeight4[index]) * e0 + detex_bptc_table_aWeight4[index] * e1 + 32) >> 6);
|
|
}
|
|
|
|
static bool DecompressBlockBPTCFloatShared(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, bool signed_flag, const uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
FDetexBlock128 block;
|
|
block.data0 = *(uint64_t *)&bitstring[0];
|
|
block.data1 = *(uint64_t *)&bitstring[8];
|
|
block.index = 0;
|
|
uint32_t mode = ExtractMode(&block);
|
|
if (mode == - 1)
|
|
return false;
|
|
// Allow compression tied to specific modes (according to mode_mask).
|
|
if (!(mode_mask & ((int)1 << mode)))
|
|
return false;
|
|
int32_t r[4], g[4], b[4];
|
|
int partition_set_id = 0;
|
|
int delta_bits_r, delta_bits_g, delta_bits_b;
|
|
uint64_t data0 = block.data0;
|
|
uint64_t data1 = block.data1;
|
|
switch (mode)
|
|
{
|
|
case 0 :
|
|
// m[1:0],g2[4],b2[4],b3[4],r0[9:0],g0[9:0],b0[9:0],r1[4:0],g3[4],g2[3:0],
|
|
// g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3]
|
|
g[2] = detexGetBits64(data0, 2, 2) << 4;
|
|
b[2] = detexGetBits64(data0, 3, 3) << 4;
|
|
b[3] = detexGetBits64(data0, 4, 4) << 4;
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 39);
|
|
g[3] = detexGetBits64(data0, 40, 40) << 4;
|
|
g[2] |= detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 49);
|
|
b[3] |= detexGetBits64(data0, 50, 50);
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 59);
|
|
b[3] |= detexGetBits64(data0, 60, 60) << 1;
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 5);
|
|
b[3] |= detexGetBits64(data1, 6, 6) << 2;
|
|
r[3] = detexGetBits64(data1, 7, 11);
|
|
b[3] |= detexGetBits64(data1, 12, 12) << 3;
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = delta_bits_g = delta_bits_b = 5;
|
|
break;
|
|
case 1 :
|
|
// m[1:0],g2[5],g3[4],g3[5],r0[6:0],b3[0],b3[1],b2[4],g0[6:0],b2[5],b3[2],
|
|
// g2[4],b0[6:0],b3[3],b3[5],b3[4],r1[5:0],g2[3:0],g1[5:0],g3[3:0],b1[5:0],
|
|
// b2[3:0],r2[5:0],r3[5:0]
|
|
g[2] = detexGetBits64(data0, 2, 2) << 5;
|
|
g[3] = detexGetBits64(data0, 3, 3) << 4;
|
|
g[3] |= detexGetBits64(data0, 4, 4) << 5;
|
|
r[0] = detexGetBits64(data0, 5, 11);
|
|
b[3] = detexGetBits64(data0, 12, 12);
|
|
b[3] |= detexGetBits64(data0, 13, 13) << 1;
|
|
b[2] = detexGetBits64(data0, 14, 14) << 4;
|
|
g[0] = detexGetBits64(data0, 15, 21);
|
|
b[2] |= detexGetBits64(data0, 22, 22) << 5;
|
|
b[3] |= detexGetBits64(data0, 23, 23) << 2;
|
|
g[2] |= detexGetBits64(data0, 24, 24) << 4;
|
|
b[0] = detexGetBits64(data0, 25, 31);
|
|
b[3] |= detexGetBits64(data0, 32, 32) << 3;
|
|
b[3] |= detexGetBits64(data0, 33, 33) << 5;
|
|
b[3] |= detexGetBits64(data0, 34, 34) << 4;
|
|
r[1] = detexGetBits64(data0, 35, 40);
|
|
g[2] |= detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 50);
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 60);
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 6);
|
|
r[3] = detexGetBits64(data1, 7, 12);
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = delta_bits_g = delta_bits_b = 6;
|
|
break;
|
|
case 2 :
|
|
// m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[4:0],r0[10],g2[3:0],g1[3:0],g0[10],
|
|
// b3[0],g3[3:0],b1[3:0],b0[10],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3]
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 39);
|
|
r[0] |= detexGetBits64(data0, 40, 40) << 10;
|
|
g[2] = detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 48);
|
|
g[0] |= detexGetBits64(data0, 49, 49) << 10;
|
|
b[3] = detexGetBits64(data0, 50, 50);
|
|
g[3] = detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 58);
|
|
b[0] |= detexGetBits64(data0, 59, 59) << 10;
|
|
b[3] |= detexGetBits64(data0, 60, 60) << 1;
|
|
b[2] = detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 5);
|
|
b[3] |= detexGetBits64(data1, 6, 6) << 2;
|
|
r[3] = detexGetBits64(data1, 7, 11);
|
|
b[3] |= detexGetBits64(data1, 12, 12) << 3;
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = 5;
|
|
delta_bits_g = delta_bits_b = 4;
|
|
break;
|
|
case 3 : // Original mode 6.
|
|
// m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10],g3[4],g2[3:0],g1[4:0],
|
|
// g0[10],g3[3:0],b1[3:0],b0[10],b3[1],b2[3:0],r2[3:0],b3[0],b3[2],r3[3:0],
|
|
// g2[4],b3[3]
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 38);
|
|
r[0] |= detexGetBits64(data0, 39, 39) << 10;
|
|
g[3] = detexGetBits64(data0, 40, 40) << 4;
|
|
g[2] = detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 49);
|
|
g[0] |= detexGetBits64(data0, 50, 50) << 10;
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 58);
|
|
b[0] |= detexGetBits64(data0, 59, 59) << 10;
|
|
b[3] = detexGetBits64(data0, 60, 60) << 1;
|
|
b[2] = detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 4);
|
|
b[3] |= detexGetBits64(data1, 5, 5);
|
|
b[3] |= detexGetBits64(data1, 6, 6) << 2;
|
|
r[3] = detexGetBits64(data1, 7, 10);
|
|
g[2] |= detexGetBits64(data1, 11, 11) << 4;
|
|
b[3] |= detexGetBits64(data1, 12, 12) << 3;
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = delta_bits_b = 4;
|
|
delta_bits_g = 5;
|
|
break;
|
|
case 4 : // Original mode 10.
|
|
// m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10],b2[4],g2[3:0],g1[3:0],
|
|
// g0[10],b3[0],g3[3:0],b1[4:0],b0[10],b2[3:0],r2[3:0],b3[1],b3[2],r3[3:0],
|
|
// b3[4],b3[3]
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 38);
|
|
r[0] |= detexGetBits64(data0, 39, 39) << 10;
|
|
b[2] = detexGetBits64(data0, 40, 40) << 4;
|
|
g[2] = detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 48);
|
|
g[0] |= detexGetBits64(data0, 49, 49) << 10;
|
|
b[3] = detexGetBits64(data0, 50, 50);
|
|
g[3] = detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 59);
|
|
b[0] |= detexGetBits64(data0, 60, 60) << 10;
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 4);
|
|
b[3] |= detexGetBits64(data1, 5, 5) << 1;
|
|
b[3] |= detexGetBits64(data1, 6, 6) << 2;
|
|
r[3] = detexGetBits64(data1, 7, 10);
|
|
b[3] |= detexGetBits64(data1, 11, 11) << 4;
|
|
b[3] |= detexGetBits64(data1, 12, 12) << 3;
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = delta_bits_g = 4;
|
|
delta_bits_b = 5;
|
|
break;
|
|
case 5 : // Original mode 14
|
|
// m[4:0],r0[8:0],b2[4],g0[8:0],g2[4],b0[8:0],b3[4],r1[4:0],g3[4],g2[3:0],
|
|
// g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],b3[2],r3[4:0],b3[3]
|
|
r[0] = detexGetBits64(data0, 5, 13);
|
|
b[2] = detexGetBits64(data0, 14, 14) << 4;
|
|
g[0] = detexGetBits64(data0, 15, 23);
|
|
g[2] = detexGetBits64(data0, 24, 24) << 4;
|
|
b[0] = detexGetBits64(data0, 25, 33);
|
|
b[3] = detexGetBits64(data0, 34, 34) << 4;
|
|
r[1] = detexGetBits64(data0, 35, 39);
|
|
g[3] = detexGetBits64(data0, 40, 40) << 4;
|
|
g[2] |= detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 49);
|
|
b[3] |= detexGetBits64(data0, 50, 50);
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 59);
|
|
b[3] |= detexGetBits64(data0, 60, 60) << 1;
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 5);
|
|
b[3] |= detexGetBits64(data1, 6, 6) << 2;
|
|
r[3] = detexGetBits64(data1, 7, 11);
|
|
b[3] |= detexGetBits64(data1, 12, 12) << 3;
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = delta_bits_g = delta_bits_b = 5;
|
|
break;
|
|
case 6 : // Original mode 18
|
|
// m[4:0],r0[7:0],g3[4],b2[4],g0[7:0],b3[2],g2[4],b0[7:0],b3[3],b3[4],
|
|
// r1[5:0],g2[3:0],g1[4:0],b3[0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[5:0],r3[5:0]
|
|
r[0] = detexGetBits64(data0, 5, 12);
|
|
g[3] = detexGetBits64(data0, 13, 13) << 4;
|
|
b[2] = detexGetBits64(data0, 14, 14) << 4;
|
|
g[0] = detexGetBits64(data0, 15, 22);
|
|
b[3] = detexGetBits64(data0, 23, 23) << 2;
|
|
g[2] = detexGetBits64(data0, 24, 24) << 4;
|
|
b[0] = detexGetBits64(data0, 25, 32);
|
|
b[3] |= detexGetBits64(data0, 33, 33) << 3;
|
|
b[3] |= detexGetBits64(data0, 34, 34) << 4;
|
|
r[1] = detexGetBits64(data0, 35, 40);
|
|
g[2] |= detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 49);
|
|
b[3] |= detexGetBits64(data0, 50, 50);
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 59);
|
|
b[3] |= detexGetBits64(data0, 60, 60) << 1;
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 6);
|
|
r[3] = detexGetBits64(data1, 7, 12);
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = 6;
|
|
delta_bits_g = delta_bits_b = 5;
|
|
break;
|
|
case 7 : // Original mode 22
|
|
// m[4:0],r0[7:0],b3[0],b2[4],g0[7:0],g2[5],g2[4],b0[7:0],g3[5],b3[4],
|
|
// r1[4:0],g3[4],g2[3:0],g1[5:0],g3[3:0],b1[4:0],b3[1],b2[3:0],r2[4:0],
|
|
// b3[2],r3[4:0],b3[3]
|
|
r[0] = detexGetBits64(data0, 5, 12);
|
|
b[3] = detexGetBits64(data0, 13, 13);
|
|
b[2] = detexGetBits64(data0, 14, 14) << 4;
|
|
g[0] = detexGetBits64(data0, 15, 22);
|
|
g[2] = detexGetBits64(data0, 23, 23) << 5;
|
|
g[2] |= detexGetBits64(data0, 24, 24) << 4;
|
|
b[0] = detexGetBits64(data0, 25, 32);
|
|
g[3] = detexGetBits64(data0, 33, 33) << 5;
|
|
b[3] |= detexGetBits64(data0, 34, 34) << 4;
|
|
r[1] = detexGetBits64(data0, 35, 39);
|
|
g[3] |= detexGetBits64(data0, 40, 40) << 4;
|
|
g[2] |= detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 50);
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 59);
|
|
b[3] |= detexGetBits64(data0, 60, 60) << 1;
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 5);
|
|
b[3] |= detexGetBits64(data1, 6, 6) << 2;
|
|
r[3] = detexGetBits64(data1, 7, 11);
|
|
b[3] |= detexGetBits64(data1, 12, 12) << 3;
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = delta_bits_b = 5;
|
|
delta_bits_g = 6;
|
|
break;
|
|
case 8 : // Original mode 26
|
|
// m[4:0],r0[7:0],b3[1],b2[4],g0[7:0],b2[5],g2[4],b0[7:0],b3[5],b3[4],
|
|
// r1[4:0],g3[4],g2[3:0],g1[4:0],b3[0],g3[3:0],b1[5:0],b2[3:0],r2[4:0],
|
|
// b3[2],r3[4:0],b3[3]
|
|
r[0] = detexGetBits64(data0, 5, 12);
|
|
b[3] = detexGetBits64(data0, 13, 13) << 1;
|
|
b[2] = detexGetBits64(data0, 14, 14) << 4;
|
|
g[0] = detexGetBits64(data0, 15, 22);
|
|
b[2] |= detexGetBits64(data0, 23, 23) << 5;
|
|
g[2] = detexGetBits64(data0, 24, 24) << 4;
|
|
b[0] = detexGetBits64(data0, 25, 32);
|
|
b[3] |= detexGetBits64(data0, 33, 33) << 5;
|
|
b[3] |= detexGetBits64(data0, 34, 34) << 4;
|
|
r[1] = detexGetBits64(data0, 35, 39);
|
|
g[3] = detexGetBits64(data0, 40, 40) << 4;
|
|
g[2] |= detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 49);
|
|
b[3] |= detexGetBits64(data0, 50, 50);
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 60);
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 5);
|
|
b[3] |= detexGetBits64(data1, 6, 6) << 2;
|
|
r[3] = detexGetBits64(data1, 7, 11);
|
|
b[3] |= detexGetBits64(data1, 12, 12) << 3;
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
delta_bits_r = delta_bits_g = 5;
|
|
delta_bits_b = 6;
|
|
break;
|
|
case 9 : // Original mode 30
|
|
// m[4:0],r0[5:0],g3[4],b3[0],b3[1],b2[4],g0[5:0],g2[5],b2[5],b3[2],
|
|
// g2[4],b0[5:0],g3[5],b3[3],b3[5],b3[4],r1[5:0],g2[3:0],g1[5:0],g3[3:0],
|
|
// b1[5:0],b2[3:0],r2[5:0],r3[5:0]
|
|
r[0] = detexGetBits64(data0, 5, 10);
|
|
g[3] = detexGetBits64(data0, 11, 11) << 4;
|
|
b[3] = detexGetBits64(data0, 12, 13);
|
|
b[2] = detexGetBits64(data0, 14, 14) << 4;
|
|
g[0] = detexGetBits64(data0, 15, 20);
|
|
g[2] = detexGetBits64(data0, 21, 21) << 5;
|
|
b[2] |= detexGetBits64(data0, 22, 22) << 5;
|
|
b[3] |= detexGetBits64(data0, 23, 23) << 2;
|
|
g[2] |= detexGetBits64(data0, 24, 24) << 4;
|
|
b[0] = detexGetBits64(data0, 25, 30);
|
|
g[3] |= detexGetBits64(data0, 31, 31) << 5;
|
|
b[3] |= detexGetBits64(data0, 32, 32) << 3;
|
|
b[3] |= detexGetBits64(data0, 33, 33) << 5;
|
|
b[3] |= detexGetBits64(data0, 34, 34) << 4;
|
|
r[1] = detexGetBits64(data0, 35, 40);
|
|
g[2] |= detexGetBits64(data0, 41, 44);
|
|
g[1] = detexGetBits64(data0, 45, 50);
|
|
g[3] |= detexGetBits64(data0, 51, 54);
|
|
b[1] = detexGetBits64(data0, 55, 60);
|
|
b[2] |= detexGetBits64(data0, 61, 63);
|
|
b[2] |= detexGetBits64(data1, 0, 0) << 3;
|
|
r[2] = detexGetBits64(data1, 1, 6);
|
|
r[3] = detexGetBits64(data1, 7, 12);
|
|
partition_set_id = detexGetBits64(data1, 13, 17);
|
|
block.index = 64 + 18;
|
|
// delta_bits_r = delta_bits_g = delta_bits_b = 6;
|
|
break;
|
|
case 10 : // Original mode 3
|
|
// m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[9:0],g1[9:0],b1[9:0]
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 44);
|
|
g[1] = detexGetBits64(data0, 45, 54);
|
|
b[1] = detexGetBits64(data0, 55, 63);
|
|
b[1] |= detexGetBits64(data1, 0, 0) << 9;
|
|
partition_set_id = 0;
|
|
block.index = 65;
|
|
// delta_bits_r = delta_bits_g = delta_bits_b = 10;
|
|
break;
|
|
case 11 : // Original mode 7
|
|
// m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[8:0],r0[10],g1[8:0],g0[10],b1[8:0],b0[10]
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 43);
|
|
r[0] |= detexGetBits64(data0, 44, 44) << 10;
|
|
g[1] = detexGetBits64(data0, 45, 53);
|
|
g[0] |= detexGetBits64(data0, 54, 54) << 10;
|
|
b[1] = detexGetBits64(data0, 55, 63);
|
|
b[0] |= detexGetBits64(data1, 0, 0) << 10;
|
|
partition_set_id = 0;
|
|
block.index = 65;
|
|
delta_bits_r = delta_bits_g = delta_bits_b = 9;
|
|
break;
|
|
case 12 : // Original mode 11
|
|
// m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[7:0],r0[10:11],g1[7:0],g0[10:11],
|
|
// b1[7:0],b0[10:11]
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 42);
|
|
r[0] |= detexGetBits64Reversed(data0, 44, 43) << 10; // Reversed.
|
|
g[1] = detexGetBits64(data0, 45, 52);
|
|
g[0] |= detexGetBits64Reversed(data0, 54, 53) << 10; // Reversed.
|
|
b[1] = detexGetBits64(data0, 55, 62);
|
|
b[0] |= detexGetBits64(data0, 63, 63) << 11; // MSB
|
|
b[0] |= detexGetBits64(data1, 0, 0) << 10; // LSB
|
|
partition_set_id = 0;
|
|
block.index = 65;
|
|
delta_bits_r = delta_bits_g = delta_bits_b = 8;
|
|
break;
|
|
case 13 : // Original mode 15
|
|
// m[4:0],r0[9:0],g0[9:0],b0[9:0],r1[3:0],r0[10:15],g1[3:0],g0[10:15],
|
|
// b1[3:0],b0[10:15]
|
|
r[0] = detexGetBits64(data0, 5, 14);
|
|
g[0] = detexGetBits64(data0, 15, 24);
|
|
b[0] = detexGetBits64(data0, 25, 34);
|
|
r[1] = detexGetBits64(data0, 35, 38);
|
|
r[0] |= detexGetBits64Reversed(data0, 44, 39) << 10; // Reversed.
|
|
g[1] = detexGetBits64(data0, 45, 48);
|
|
g[0] |= detexGetBits64Reversed(data0, 54, 49) << 10; // Reversed.
|
|
b[1] = detexGetBits64(data0, 55, 58);
|
|
b[0] |= detexGetBits64Reversed(data0, 63, 59) << 11; // Reversed.
|
|
b[0] |= detexGetBits64(data1, 0, 0) << 10;
|
|
partition_set_id = 0;
|
|
block.index = 65;
|
|
delta_bits_r = delta_bits_g = delta_bits_b = 4;
|
|
break;
|
|
}
|
|
int nu_subsets;
|
|
if (mode >= 10)
|
|
nu_subsets = 1;
|
|
else
|
|
nu_subsets = 2;
|
|
if (signed_flag)
|
|
{
|
|
r[0] = SignExtend(r[0], bptc_float_EPB[mode], 32);
|
|
g[0] = SignExtend(g[0], bptc_float_EPB[mode], 32);
|
|
b[0] = SignExtend(b[0], bptc_float_EPB[mode], 32);
|
|
}
|
|
if (mode != 9 && mode != 10)
|
|
{
|
|
// Transformed endpoints.
|
|
for (int i = 1; i < nu_subsets * 2; i++)
|
|
{
|
|
r[i] = SignExtend(r[i], delta_bits_r, 32);
|
|
r[i] = (r[0] + r[i]) & (((uint32_t)1 << bptc_float_EPB[mode]) - 1);
|
|
g[i] = SignExtend(g[i], delta_bits_g, 32);
|
|
g[i] = (g[0] + g[i]) & (((uint32_t)1 << bptc_float_EPB[mode]) - 1);
|
|
b[i] = SignExtend(b[i], delta_bits_b, 32);
|
|
b[i] = (b[0] + b[i]) & (((uint32_t)1 << bptc_float_EPB[mode]) - 1);
|
|
if (signed_flag)
|
|
{
|
|
r[i] = SignExtend(r[i], bptc_float_EPB[mode], 32);
|
|
g[i] = SignExtend(g[i], bptc_float_EPB[mode], 32);
|
|
b[i] = SignExtend(b[i], bptc_float_EPB[mode], 32);
|
|
}
|
|
}
|
|
}
|
|
else // Mode 9 or 10, no transformed endpoints.
|
|
{
|
|
if (signed_flag)
|
|
{
|
|
for (int i = 1; i < nu_subsets * 2; i++)
|
|
{
|
|
r[i] = SignExtend(r[i], bptc_float_EPB[mode], 32);
|
|
g[i] = SignExtend(g[i], bptc_float_EPB[mode], 32);
|
|
b[i] = SignExtend(b[i], bptc_float_EPB[mode], 32);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Unquantize endpoints.
|
|
if (signed_flag)
|
|
{
|
|
for (int i = 0; i < 2 * nu_subsets; i++)
|
|
{
|
|
r[i] = UnquantizeSigned(r[i], mode);
|
|
g[i] = UnquantizeSigned(g[i], mode);
|
|
b[i] = UnquantizeSigned(b[i], mode);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < 2 * nu_subsets; i++)
|
|
{
|
|
r[i] = Unquantize(r[i], mode);
|
|
g[i] = Unquantize(g[i], mode);
|
|
b[i] = Unquantize(b[i], mode);
|
|
}
|
|
}
|
|
|
|
uint8_t subset_index[16];
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
// subset_index[i] is a number from 0 to 1, depending on the number of subsets.
|
|
subset_index[i] = GetPartitionIndex(nu_subsets, partition_set_id, i);
|
|
}
|
|
uint8_t anchor_index[4]; // Only need max. 2 elements
|
|
for (int i = 0; i < nu_subsets; i++)
|
|
{
|
|
anchor_index[i] = GetAnchorIndex(partition_set_id, i, nu_subsets);
|
|
}
|
|
uint8_t color_index[16];
|
|
// Extract index bits.
|
|
int color_index_bit_count = 3;
|
|
if ((bitstring[0] & 3) == 3) // This defines original modes 3, 7, 11, 15
|
|
color_index_bit_count = 4;
|
|
// Because the index bits are all in the second 64-bit word, there is no need to use
|
|
// block_extract_bits().
|
|
data1 >>= (block.index - 64);
|
|
uint8_t mask1 = (1 << color_index_bit_count) - 1;
|
|
uint8_t mask2 = (1 << (color_index_bit_count - 1)) - 1;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
if (i == anchor_index[subset_index[i]])
|
|
{
|
|
// Highest bit is zero.
|
|
// color_index[i] = block_extract_bits(&block, color_index_bit_count - 1);
|
|
color_index[i] = data1 & mask2;
|
|
data1 >>= color_index_bit_count - 1;
|
|
}
|
|
else
|
|
{
|
|
// color_index[i] = block_extract_bits(&block, color_index_bit_count);
|
|
color_index[i] = data1 & mask1;
|
|
data1 >>= color_index_bit_count;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int32_t endpoint_start_r, endpoint_start_g, endpoint_start_b;
|
|
int32_t endpoint_end_r, endpoint_end_g, endpoint_end_b;
|
|
endpoint_start_r = r[2 * subset_index[i]];
|
|
endpoint_end_r = r[2 * subset_index[i] + 1];
|
|
endpoint_start_g = g[2 * subset_index[i]];
|
|
endpoint_end_g = g[2 * subset_index[i] + 1];
|
|
endpoint_start_b = b[2 * subset_index[i]];
|
|
endpoint_end_b = b[2 * subset_index[i] + 1];
|
|
uint64_t output;
|
|
if (signed_flag)
|
|
{
|
|
int32_t r16 = InterpolateFloat(endpoint_start_r, endpoint_end_r, color_index[i], color_index_bit_count);
|
|
if (r16 < 0)
|
|
r16 = - (((- r16) * 31) >> 5);
|
|
else
|
|
r16 = (r16 * 31) >> 5;
|
|
int s = 0;
|
|
if (r16 < 0)
|
|
{
|
|
s = 0x8000;
|
|
r16 = - r16;
|
|
}
|
|
r16 |= s;
|
|
int32_t g16 = InterpolateFloat(endpoint_start_g, endpoint_end_g, color_index[i], color_index_bit_count);
|
|
if (g16 < 0)
|
|
g16 = - (((- g16) * 31) >> 5);
|
|
else
|
|
g16 = (g16 * 31) >> 5;
|
|
s = 0;
|
|
if (g16 < 0)
|
|
{
|
|
s = 0x8000;
|
|
g16 = - g16;
|
|
}
|
|
g16 |= s;
|
|
int32_t b16 = InterpolateFloat(endpoint_start_b, endpoint_end_b, color_index[i], color_index_bit_count);
|
|
if (b16 < 0)
|
|
b16 = - (((- b16) * 31) >> 5);
|
|
else
|
|
b16 = (b16 * 31) >> 5;
|
|
s = 0;
|
|
if (b16 < 0)
|
|
{
|
|
s = 0x8000;
|
|
b16 = - b16;
|
|
}
|
|
b16 |= s;
|
|
output = detexPack64RGB16(r16, g16, b16);
|
|
}
|
|
else
|
|
{
|
|
output = detexPack64R16(InterpolateFloat(endpoint_start_r, endpoint_end_r, color_index[i], color_index_bit_count) * 31 / 64);
|
|
output |= detexPack64G16(InterpolateFloat(endpoint_start_g, endpoint_end_g, color_index[i], color_index_bit_count) * 31 / 64);
|
|
output |= detexPack64B16(InterpolateFloat(endpoint_start_b, endpoint_end_b, color_index[i], color_index_bit_count) * 31 / 64);
|
|
}
|
|
*(uint64_t *)&pixel_buffer[i * 8] = output;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static uint8_t Interpolate(uint8_t e0, uint8_t e1, uint8_t index, uint8_t indexprecision)
|
|
{
|
|
if (indexprecision == 2)
|
|
return (uint8_t)(((64 - detex_bptc_table_aWeight2[index]) * (uint16_t)e0 + detex_bptc_table_aWeight2[index] * (uint16_t)e1 + 32) >> 6);
|
|
else
|
|
if (indexprecision == 3)
|
|
return (uint8_t)(((64 - detex_bptc_table_aWeight3[index]) * (uint16_t)e0 + detex_bptc_table_aWeight3[index] * (uint16_t)e1 + 32) >> 6);
|
|
else // indexprecision == 4
|
|
return (uint8_t)(((64 - detex_bptc_table_aWeight4[index]) * (uint16_t)e0 + detex_bptc_table_aWeight4[index] * (uint16_t)e1 + 32) >> 6);
|
|
}
|
|
|
|
static const uint8_t IB[8] = { 3, 3, 2, 2, 2, 2, 4, 2 };
|
|
static const uint8_t IB2[8] = { 0, 0, 0, 0, 3, 2, 0, 0 };
|
|
static const uint8_t mode_has_partition_bits[8] = { 1, 1, 1, 1, 0, 0, 0, 1 };
|
|
|
|
static const uint8_t bptc_color_index_bitcount[8] = { 3, 3, 2, 2, 2, 2, 4, 2 };
|
|
|
|
static DETEX_INLINE_ONLY int GetColorIndexBitcount(int mode, int index_selection_bit)
|
|
{
|
|
// If the index selection bit is set for mode 4, return 3, otherwise 2.
|
|
return bptc_color_index_bitcount[mode] + index_selection_bit;
|
|
}
|
|
|
|
static uint8_t bptc_alpha_index_bitcount[8] = { 3, 3, 2, 2, 3, 2, 4, 2 };
|
|
|
|
static DETEX_INLINE_ONLY int GetAlphaIndexBitcount(int mode, int index_selection_bit)
|
|
{
|
|
// If the index selection bit is set for mode 4, return 2, otherwise 3.
|
|
return bptc_alpha_index_bitcount[mode] - index_selection_bit;
|
|
}
|
|
|
|
static const uint8_t bptc_NS[8] = { 3, 2, 3, 2, 1, 1, 1, 2 };
|
|
|
|
static DETEX_INLINE_ONLY int GetNumberOfSubsets(int mode)
|
|
{
|
|
return bptc_NS[mode];
|
|
}
|
|
|
|
static const uint8_t PB[8] = { 4, 6, 6, 6, 0, 0, 0, 6 };
|
|
|
|
static DETEX_INLINE_ONLY int GetNumberOfPartitionBits(int mode)
|
|
{
|
|
return PB[mode];
|
|
}
|
|
|
|
static const uint8_t RB[8] = { 0, 0, 0, 0, 2, 2, 0, 0 };
|
|
|
|
static DETEX_INLINE_ONLY int GetNumberOfRotationBits(int mode)
|
|
{
|
|
return RB[mode];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int ExtractPartitionSetID(FDetexBlock128 *block, int mode)
|
|
{
|
|
return detexBlock128ExtractBits(block, GetNumberOfPartitionBits(mode));
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int ExtractRotationBits(FDetexBlock128 *block, int mode)
|
|
{
|
|
return detexBlock128ExtractBits(block, GetNumberOfRotationBits(mode));
|
|
}
|
|
|
|
static const int8_t components_in_qword0_table[8] = { 2, -1, 1, 1, 3, 3, 3, 2 };
|
|
|
|
static const uint8_t color_precision_table[8] = { 4, 6, 5, 7, 5, 7, 7, 5 };
|
|
|
|
// Note: precision includes P-bits!
|
|
static const uint8_t color_precision_plus_pbit_table[8] = { 5, 7, 5, 8, 5, 7, 8, 6 };
|
|
|
|
static DETEX_INLINE_ONLY uint8_t GetColorComponentPrecision(int mode)
|
|
{
|
|
return color_precision_table[mode];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY uint8_t GetColorComponentPrecisionPlusPbit(int mode)
|
|
{
|
|
return color_precision_plus_pbit_table[mode];
|
|
}
|
|
|
|
static const int8_t alpha_precision_table[8] = { 0, 0, 0, 0, 6, 8, 7, 5 };
|
|
|
|
// Note: precision include P-bits!
|
|
static const uint8_t alpha_precision_plus_pbit_table[8] = { 0, 0, 0, 0, 6, 8, 8, 6 };
|
|
|
|
static DETEX_INLINE_ONLY uint8_t GetAlphaComponentPrecision(int mode)
|
|
{
|
|
return alpha_precision_table[mode];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY uint8_t GetAlphaComponentPrecisionPlusPbit(int mode)
|
|
{
|
|
return alpha_precision_plus_pbit_table[mode];
|
|
}
|
|
|
|
/* Extract endpoint colors. */
|
|
static void ExtractEndpoints(int mode, int nu_subsets, FDetexBlock128 * DETEX_RESTRICT block, uint8_t * DETEX_RESTRICT endpoint_array)
|
|
{
|
|
// Optimized version avoiding the use of block_extract_bits().
|
|
int components_in_qword0 = components_in_qword0_table[mode];
|
|
uint64_t data = block->data0 >> block->index;
|
|
uint8_t precision = GetColorComponentPrecision(mode);
|
|
uint8_t mask = (1 << precision) - 1;
|
|
int total_bits_per_component = nu_subsets * 2 * precision;
|
|
for (int i = 0; i < components_in_qword0; i++) // For each color component.
|
|
{
|
|
for (int j = 0; j < nu_subsets; j++) // For each subset.
|
|
{
|
|
for (int k = 0; k < 2; k++)
|
|
{ // For each endpoint.
|
|
endpoint_array[j * 8 + k * 4 + i] = data & mask;
|
|
data >>= precision;
|
|
}
|
|
}
|
|
}
|
|
block->index += components_in_qword0 * total_bits_per_component;
|
|
if (components_in_qword0 < 3)
|
|
{
|
|
// Handle the color component that crosses the boundary between data0 and data1
|
|
data = block->data0 >> block->index;
|
|
data |= block->data1 << (64 - block->index);
|
|
int i = components_in_qword0;
|
|
for (int j = 0; j < nu_subsets; j++) // For each subset.
|
|
{
|
|
for (int k = 0; k < 2; k++)
|
|
{ // For each endpoint.
|
|
endpoint_array[j * 8 + k * 4 + i] = data & mask;
|
|
data >>= precision;
|
|
}
|
|
}
|
|
block->index += total_bits_per_component;
|
|
}
|
|
if (components_in_qword0 < 2)
|
|
{
|
|
// Handle the color component that is wholly in data1.
|
|
data = block->data1 >> (block->index - 64);
|
|
int i = 2;
|
|
for (int j = 0; j < nu_subsets; j++) // For each subset.
|
|
{
|
|
for (int k = 0; k < 2; k++)
|
|
{ // For each endpoint.
|
|
endpoint_array[j * 8 + k * 4 + i] = data & mask;
|
|
data >>= precision;
|
|
}
|
|
}
|
|
block->index += total_bits_per_component;
|
|
}
|
|
// Alpha component.
|
|
if (GetAlphaComponentPrecision(mode) > 0)
|
|
{
|
|
// For mode 7, the alpha data is wholly in data1.
|
|
// For modes 4 and 6, the alpha data is wholly in data0.
|
|
// For mode 5, the alpha data is in data0 and data1.
|
|
if (mode == 7)
|
|
data = block->data1 >> (block->index - 64);
|
|
else if (mode == 5)
|
|
data = (block->data0 >> block->index) | ((block->data1 & 0x3) << 14);
|
|
else
|
|
data = block->data0 >> block->index;
|
|
uint8_t alpha_precision = GetAlphaComponentPrecision(mode);
|
|
uint8_t amask = (1 << alpha_precision) - 1;
|
|
for (int j = 0; j < nu_subsets; j++)
|
|
{
|
|
for (int k = 0; k < 2; k++)
|
|
{ // For each endpoint.
|
|
endpoint_array[j * 8 + k * 4 + 3] = data & amask;
|
|
data >>= alpha_precision;
|
|
}
|
|
}
|
|
block->index += nu_subsets * 2 * alpha_precision;
|
|
}
|
|
}
|
|
|
|
static const uint8_t mode_has_p_bits[8] = { 1, 1, 0, 1, 0, 0, 1, 1 };
|
|
|
|
static void FullyDecodeEndpoints(uint8_t * DETEX_RESTRICT endpoint_array, int nu_subsets, int mode, FDetexBlock128 * DETEX_RESTRICT block)
|
|
{
|
|
if (mode_has_p_bits[mode])
|
|
{
|
|
// Mode 1 (shared P-bits) handled elsewhere.
|
|
// Extract end-point P-bits. Take advantage of the fact that they don't cross the
|
|
// 64-bit word boundary in any mode.
|
|
uint32_t bits;
|
|
if (block->index < 64)
|
|
bits = block->data0 >> block->index;
|
|
else
|
|
bits = block->data1 >> (block->index - 64);
|
|
for (int i = 0; i < nu_subsets * 2; i++)
|
|
{
|
|
endpoint_array[i * 4 + 0] <<= 1;
|
|
endpoint_array[i * 4 + 1] <<= 1;
|
|
endpoint_array[i * 4 + 2] <<= 1;
|
|
endpoint_array[i * 4 + 3] <<= 1;
|
|
endpoint_array[i * 4 + 0] |= (bits & 1);
|
|
endpoint_array[i * 4 + 1] |= (bits & 1);
|
|
endpoint_array[i * 4 + 2] |= (bits & 1);
|
|
endpoint_array[i * 4 + 3] |= (bits & 1);
|
|
bits >>= 1;
|
|
}
|
|
block->index += nu_subsets * 2;
|
|
}
|
|
int color_prec = GetColorComponentPrecisionPlusPbit(mode);
|
|
int alpha_prec = GetAlphaComponentPrecisionPlusPbit(mode);
|
|
for (int i = 0; i < nu_subsets * 2; i++)
|
|
{
|
|
// Color_component_precision & alpha_component_precision includes pbit
|
|
// left shift endpoint components so that their MSB lies in bit 7
|
|
endpoint_array[i * 4 + 0] <<= (8 - color_prec);
|
|
endpoint_array[i * 4 + 1] <<= (8 - color_prec);
|
|
endpoint_array[i * 4 + 2] <<= (8 - color_prec);
|
|
endpoint_array[i * 4 + 3] <<= (8 - alpha_prec);
|
|
|
|
// Replicate each component's MSB into the LSBs revealed by the left-shift operation above.
|
|
endpoint_array[i * 4 + 0] |= (endpoint_array[i * 4 + 0] >> color_prec);
|
|
endpoint_array[i * 4 + 1] |= (endpoint_array[i * 4 + 1] >> color_prec);
|
|
endpoint_array[i * 4 + 2] |= (endpoint_array[i * 4 + 2] >> color_prec);
|
|
endpoint_array[i * 4 + 3] |= (endpoint_array[i * 4 + 3] >> alpha_prec);
|
|
}
|
|
if (mode <= 3)
|
|
{
|
|
for (int i = 0; i < nu_subsets * 2; i++)
|
|
endpoint_array[i * 4 + 3] = 0xFF;
|
|
}
|
|
}
|
|
|
|
/* Decompress a 128-bit 4x4 pixel texture block compressed using BPTC mode 1. */
|
|
|
|
static bool DecompressBlockBPTCMode1(FDetexBlock128 * DETEX_RESTRICT block, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
uint64_t data0 = block->data0;
|
|
uint64_t data1 = block->data1;
|
|
int partition_set_id = detexGetBits64(data0, 2, 7);
|
|
uint8_t endpoint[2 * 2 * 3]; // 2 subsets.
|
|
endpoint[0] = detexGetBits64(data0, 8, 13); // red, subset 0, endpoint 0
|
|
endpoint[3] = detexGetBits64(data0, 14, 19); // red, subset 0, endpoint 1
|
|
endpoint[6] = detexGetBits64(data0, 20, 25); // red, subset 1, endpoint 0
|
|
endpoint[9] = detexGetBits64(data0, 26, 31); // red, subset 1, endpoint 1
|
|
endpoint[1] = detexGetBits64(data0, 32, 37); // green, subset 0, endpoint 0
|
|
endpoint[4] = detexGetBits64(data0, 38, 43); // green, subset 0, endpoint 1
|
|
endpoint[7] = detexGetBits64(data0, 44, 49); // green, subset 1, endpoint 0
|
|
endpoint[10] = detexGetBits64(data0, 50, 55); // green, subset 1, endpoint 1
|
|
endpoint[2] = detexGetBits64(data0, 56, 61); // blue, subset 0, endpoint 0
|
|
endpoint[5] = detexGetBits64(data0, 62, 63) // blue, subset 0, endpoint 1
|
|
| (detexGetBits64(data1, 0, 3) << 2);
|
|
endpoint[8] = detexGetBits64(data1, 4, 9); // blue, subset 1, endpoint 0
|
|
endpoint[11] = detexGetBits64(data1, 10, 15); // blue, subset 1, endpoint 1
|
|
// Decode endpoints.
|
|
for (int i = 0; i < 2 * 2; i++)
|
|
{
|
|
//component-wise left-shift
|
|
endpoint[i * 3 + 0] <<= 2;
|
|
endpoint[i * 3 + 1] <<= 2;
|
|
endpoint[i * 3 + 2] <<= 2;
|
|
}
|
|
// P-bit is shared.
|
|
uint8_t pbit_zero = detexGetBits64(data1, 16, 16) << 1;
|
|
uint8_t pbit_one = detexGetBits64(data1, 17, 17) << 1;
|
|
// RGB only pbits for mode 1, one for each subset.
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
endpoint[0 * 3 + j] |= pbit_zero;
|
|
endpoint[1 * 3 + j] |= pbit_zero;
|
|
endpoint[2 * 3 + j] |= pbit_one;
|
|
endpoint[3 * 3 + j] |= pbit_one;
|
|
}
|
|
for (int i = 0; i < 2 * 2; i++)
|
|
{
|
|
// Replicate each component's MSB into the LSB.
|
|
endpoint[i * 3 + 0] |= endpoint[i * 3 + 0] >> 7;
|
|
endpoint[i * 3 + 1] |= endpoint[i * 3 + 1] >> 7;
|
|
endpoint[i * 3 + 2] |= endpoint[i * 3 + 2] >> 7;
|
|
}
|
|
|
|
uint8_t subset_index[16];
|
|
for (int i = 0; i < 16; i++)
|
|
// subset_index[i] is a number from 0 to 1.
|
|
subset_index[i] = detex_bptc_table_P2[partition_set_id * 16 + i];
|
|
uint8_t anchor_index[2];
|
|
anchor_index[0] = 0;
|
|
anchor_index[1] = detex_bptc_table_anchor_index_second_subset[partition_set_id];
|
|
uint8_t color_index[16];
|
|
// Extract primary index bits.
|
|
data1 >>= 18;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
if (i == anchor_index[subset_index[i]])
|
|
{
|
|
// Highest bit is zero.
|
|
color_index[i] = data1 & 3; // Get two bits.
|
|
data1 >>= 2;
|
|
}
|
|
else
|
|
{
|
|
color_index[i] = data1 & 7; // Get three bits.
|
|
data1 >>= 3;
|
|
}
|
|
}
|
|
uint32_t *pixel32_buffer = (uint32_t *)pixel_buffer;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
uint8_t endpoint_start[3];
|
|
uint8_t endpoint_end[3];
|
|
for (int j = 0; j < 3; j++)
|
|
{
|
|
endpoint_start[j] = endpoint[2 * subset_index[i] * 3 + j];
|
|
endpoint_end[j] = endpoint[(2 * subset_index[i] + 1) * 3 + j];
|
|
}
|
|
uint32_t output;
|
|
output = detexPack32R8(Interpolate(endpoint_start[0], endpoint_end[0], color_index[i], 3));
|
|
output |= detexPack32G8(Interpolate(endpoint_start[1], endpoint_end[1], color_index[i], 3));
|
|
output |= detexPack32B8(Interpolate(endpoint_start[2], endpoint_end[2], color_index[i], 3));
|
|
output |= detexPack32A8(0xFF);
|
|
pixel32_buffer[i] = output;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/* Decompress a 128-bit 4x4 pixel texture block compressed using the BPTC */
|
|
/* (BC7) format. */
|
|
bool detexDecompressBlockBPTC(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
FDetexBlock128 block;
|
|
block.data0 = *(uint64_t *)&bitstring[0];
|
|
block.data1 = *(uint64_t *)&bitstring[8];
|
|
block.index = 0;
|
|
int mode = ExtractMode(&block);
|
|
if (mode == -1)
|
|
return 0;
|
|
// Allow compression tied to specific modes (according to mode_mask).
|
|
if (!(mode_mask & ((int)1 << mode)))
|
|
return 0;
|
|
if (mode >= 4 && (flags & DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY))
|
|
return 0;
|
|
if (mode < 4 && (flags & DETEX_DECOMPRESS_FLAG_NON_OPAQUE_ONLY))
|
|
return 0;
|
|
if (mode == 1)
|
|
return DecompressBlockBPTCMode1(&block, pixel_buffer);
|
|
|
|
int nu_subsets = 1;
|
|
int partition_set_id = 0;
|
|
if (mode_has_partition_bits[mode])
|
|
{
|
|
nu_subsets = GetNumberOfSubsets(mode);
|
|
partition_set_id = ExtractPartitionSetID(&block, mode);
|
|
}
|
|
int rotation = ExtractRotationBits(&block, mode);
|
|
int index_selection_bit = 0;
|
|
if (mode == 4)
|
|
index_selection_bit = detexBlock128ExtractBits(&block, 1);
|
|
|
|
int alpha_index_bitcount = GetAlphaIndexBitcount(mode, index_selection_bit);
|
|
int color_index_bitcount = GetColorIndexBitcount(mode, index_selection_bit);
|
|
|
|
uint8_t endpoint_array[3 * 2 * 4]; // Max. 3 subsets.
|
|
ExtractEndpoints(mode, nu_subsets, &block, endpoint_array);
|
|
FullyDecodeEndpoints(endpoint_array, nu_subsets, mode, &block);
|
|
|
|
uint8_t subset_index[16];
|
|
for (int i = 0; i < 16; i++)
|
|
// subset_index[i] is a number from 0 to 2, or 0 to 1, or 0 depending on the number of subsets.
|
|
subset_index[i] = GetPartitionIndex(nu_subsets, partition_set_id, i);
|
|
uint8_t anchor_index[4]; // Only need max. 3 elements.
|
|
for (int i = 0; i < nu_subsets; i++)
|
|
anchor_index[i] = GetAnchorIndex(partition_set_id, i, nu_subsets);
|
|
uint8_t color_index[16];
|
|
uint8_t alpha_index[16];
|
|
// Extract primary index bits.
|
|
uint64_t data1;
|
|
if (block.index >= 64)
|
|
{
|
|
// Because the index bits are all in the second 64-bit word, there is no need to use
|
|
// block_extract_bits().
|
|
// This implies the mode is not 4.
|
|
data1 = block.data1 >> (block.index - 64);
|
|
uint8_t mask1 = (1 << IB[mode]) - 1;
|
|
uint8_t mask2 = (1 << (IB[mode] - 1)) - 1;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
if (i == anchor_index[subset_index[i]])
|
|
{
|
|
// Highest bit is zero.
|
|
color_index[i] = data1 & mask2;
|
|
data1 >>= IB[mode] - 1;
|
|
alpha_index[i] = color_index[i];
|
|
}
|
|
else
|
|
{
|
|
color_index[i] = data1 & mask1;
|
|
data1 >>= IB[mode];
|
|
alpha_index[i] = color_index[i];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{ // Implies mode 4.
|
|
// Because the bits cross the 64-bit word boundary, we have to be careful.
|
|
// Block index is 50 at this point.
|
|
uint64_t data = block.data0 >> 50;
|
|
data |= block.data1 << 14;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
if (i == anchor_index[subset_index[i]])
|
|
{
|
|
// Highest bit is zero.
|
|
if (index_selection_bit) { // Implies mode == 4.
|
|
alpha_index[i] = data & 0x1;
|
|
data >>= 1;
|
|
}
|
|
else
|
|
{
|
|
color_index[i] = data & 0x1;
|
|
data >>= 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (index_selection_bit)
|
|
{ // Implies mode == 4.
|
|
alpha_index[i] = data & 0x3;
|
|
data >>= 2;
|
|
}
|
|
else
|
|
{
|
|
color_index[i] = data & 0x3;
|
|
data >>= 2;
|
|
}
|
|
}
|
|
// Block index is 81 at this point.
|
|
data1 = block.data1 >> (81 - 64);
|
|
}
|
|
}
|
|
// Extract secondary index bits.
|
|
if (IB2[mode] > 0)
|
|
{
|
|
uint8_t mask1 = (1 << IB2[mode]) - 1;
|
|
uint8_t mask2 = (1 << (IB2[mode] - 1)) - 1;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
if (i == anchor_index[subset_index[i]])
|
|
{
|
|
// Highest bit is zero.
|
|
if (index_selection_bit)
|
|
{
|
|
color_index[i] = data1 & 0x3;
|
|
data1 >>= 2;
|
|
}
|
|
else
|
|
{
|
|
// alpha_index[i] = block_extract_bits(&block, IB2[mode] - 1);
|
|
alpha_index[i] = data1 & mask2;
|
|
data1 >>= IB2[mode] - 1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (index_selection_bit)
|
|
{
|
|
color_index[i] = data1 & 0x7;
|
|
data1 >>= 3;
|
|
}
|
|
else
|
|
{
|
|
// alpha_index[i] = block_extract_bits(&block, IB2[mode]);
|
|
alpha_index[i] = data1 & mask1;
|
|
data1 >>= IB2[mode];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t *pixel32_buffer = (uint32_t *)pixel_buffer;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
uint8_t endpoint_start[4];
|
|
uint8_t endpoint_end[4];
|
|
for (int j = 0; j < 4; j++)
|
|
{
|
|
endpoint_start[j] = endpoint_array[2 * subset_index[i] * 4 + j];
|
|
endpoint_end[j] = endpoint_array[(2 * subset_index[i] + 1) * 4 + j];
|
|
}
|
|
|
|
uint32_t output = 0;
|
|
output = detexPack32R8(Interpolate(endpoint_start[0], endpoint_end[0], color_index[i], color_index_bitcount));
|
|
output |= detexPack32G8(Interpolate(endpoint_start[1], endpoint_end[1], color_index[i], color_index_bitcount));
|
|
output |= detexPack32B8(Interpolate(endpoint_start[2], endpoint_end[2], color_index[i], color_index_bitcount));
|
|
output |= detexPack32A8(Interpolate(endpoint_start[3], endpoint_end[3], alpha_index[i], alpha_index_bitcount));
|
|
|
|
if (rotation > 0)
|
|
{
|
|
if (rotation == 1)
|
|
output = detexPack32RGBA8(detexPixel32GetA8(output), detexPixel32GetG8(output), detexPixel32GetB8(output), detexPixel32GetR8(output));
|
|
else
|
|
{
|
|
if (rotation == 2)
|
|
output = detexPack32RGBA8(detexPixel32GetR8(output), detexPixel32GetA8(output), detexPixel32GetB8(output), detexPixel32GetG8(output));
|
|
else // rotation == 3
|
|
output = detexPack32RGBA8(detexPixel32GetR8(output), detexPixel32GetG8(output), detexPixel32GetA8(output), detexPixel32GetB8(output));
|
|
}
|
|
}
|
|
pixel32_buffer[i] = output;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
Decompress a 128-bit 4x4 pixel texture block compressed using the
|
|
BPTC_FLOAT (BC6H) format. The output format is
|
|
DETEX_PIXEL_FORMAT_FLOAT_RGBX16.
|
|
*/
|
|
bool detexDecompressBlockBPTC_FLOAT(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
return DecompressBlockBPTCFloatShared(bitstring, mode_mask, flags, false, pixel_buffer);
|
|
}
|
|
|
|
/**
|
|
Decompress a 128-bit 4x4 pixel texture block compressed using the
|
|
BPTC_FLOAT (BC6H_FLOAT) format. The output format is
|
|
DETEX_PIXEL_FORMAT_SIGNED_FLOAT_RGBX16.
|
|
*/
|
|
bool detexDecompressBlockBPTC_SIGNED_FLOAT(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
return DecompressBlockBPTCFloatShared(bitstring, mode_mask, flags, true, pixel_buffer);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////////////
|
|
static DETEX_INLINE_ONLY int clamp2047(int x)
|
|
{
|
|
if (x < 0)
|
|
return 0;
|
|
if (x > 2047)
|
|
return 2047;
|
|
return x;
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int clamp1023_signed(int x)
|
|
{
|
|
if (x < -1023)
|
|
return -1023;
|
|
if (x > 1023)
|
|
return 1023;
|
|
return x;
|
|
}
|
|
|
|
/** Clamp an integer value in the range -255 to 511 to the the range 0 to 255. */
|
|
static DETEX_INLINE_ONLY uint8_t detexClamp0To255(int x)
|
|
{
|
|
return detex_clamp0to255_table[x + 255];
|
|
}
|
|
|
|
// This function calculates the 3-bit complement value in the range -4 to 3 of a three bit
|
|
// representation. The result is arithmetically shifted 3 places to the left before returning.
|
|
static DETEX_INLINE_ONLY int complement3bitshifted(int x)
|
|
{
|
|
return complement3bitshifted_table[x];
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int complement3bitshifted_slow(int x)
|
|
{
|
|
if (x & 4)
|
|
return ((x & 3) - 4) << 3; // Note: shift is arithmetic.
|
|
return x << 3;
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY int complement3bit(int x)
|
|
{
|
|
if (x & 4)
|
|
return ((x & 3) - 4);
|
|
return x;
|
|
}
|
|
|
|
// Define inline function to speed up ETC1 decoding.
|
|
|
|
static DETEX_INLINE_ONLY void ProcessPixelETC1(uint8_t i, uint32_t pixel_index_word, uint32_t table_codeword, int * DETEX_RESTRICT base_color_subblock, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int pixel_index = ((pixel_index_word & (1 << i)) >> i) | ((pixel_index_word & (0x10000 << i)) >> (16 + i - 1));
|
|
int r, g, b;
|
|
int modifier = modifier_table[table_codeword][pixel_index];
|
|
r = detexClamp0To255(base_color_subblock[0] + modifier);
|
|
g = detexClamp0To255(base_color_subblock[1] + modifier);
|
|
b = detexClamp0To255(base_color_subblock[2] + modifier);
|
|
uint32_t *buffer = (uint32_t *)pixel_buffer;
|
|
buffer[(i & 3) * 4 + ((i & 12) >> 2)] = detexPack32RGB8Alpha0xFF(r, g, b);
|
|
}
|
|
|
|
/* Decompress a 64-bit 4x4 pixel texture block compressed using the ETC1 */
|
|
/* format. */
|
|
bool detexDecompressBlockETC1(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int differential_mode = bitstring[3] & 2;
|
|
if (differential_mode)
|
|
{
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_DIFFERENTIAL) == 0)
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_INDIVIDUAL) == 0)
|
|
return false;
|
|
}
|
|
int flipbit = bitstring[3] & 1;
|
|
int base_color_subblock1[3];
|
|
int base_color_subblock2[3];
|
|
if (differential_mode)
|
|
{
|
|
base_color_subblock1[0] = (bitstring[0] & 0xF8);
|
|
base_color_subblock1[0] |= ((base_color_subblock1[0] & 224) >> 5);
|
|
base_color_subblock1[1] = (bitstring[1] & 0xF8);
|
|
base_color_subblock1[1] |= (base_color_subblock1[1] & 224) >> 5;
|
|
base_color_subblock1[2] = (bitstring[2] & 0xF8);
|
|
base_color_subblock1[2] |= (base_color_subblock1[2] & 224) >> 5;
|
|
base_color_subblock2[0] = (bitstring[0] & 0xF8); // 5 highest order bits.
|
|
base_color_subblock2[0] += complement3bitshifted(bitstring[0] & 7); // Add difference.
|
|
if (base_color_subblock2[0] & 0xFF07) // Check for overflow.
|
|
return false;
|
|
base_color_subblock2[0] |= (base_color_subblock2[0] & 224) >> 5; // Replicate.
|
|
base_color_subblock2[1] = (bitstring[1] & 0xF8);
|
|
base_color_subblock2[1] += complement3bitshifted(bitstring[1] & 7);
|
|
if (base_color_subblock2[1] & 0xFF07)
|
|
return false;
|
|
base_color_subblock2[1] |= (base_color_subblock2[1] & 224) >> 5;
|
|
base_color_subblock2[2] = (bitstring[2] & 0xF8);
|
|
base_color_subblock2[2] += complement3bitshifted(bitstring[2] & 7);
|
|
if (base_color_subblock2[2] & 0xFF07)
|
|
return false;
|
|
base_color_subblock2[2] |= (base_color_subblock2[2] & 224) >> 5;
|
|
}
|
|
else
|
|
{
|
|
base_color_subblock1[0] = (bitstring[0] & 0xF0);
|
|
base_color_subblock1[0] |= base_color_subblock1[0] >> 4;
|
|
base_color_subblock1[1] = (bitstring[1] & 0xF0);
|
|
base_color_subblock1[1] |= base_color_subblock1[1] >> 4;
|
|
base_color_subblock1[2] = (bitstring[2] & 0xF0);
|
|
base_color_subblock1[2] |= base_color_subblock1[2] >> 4;
|
|
base_color_subblock2[0] = (bitstring[0] & 0x0F);
|
|
base_color_subblock2[0] |= base_color_subblock2[0] << 4;
|
|
base_color_subblock2[1] = (bitstring[1] & 0x0F);
|
|
base_color_subblock2[1] |= base_color_subblock2[1] << 4;
|
|
base_color_subblock2[2] = (bitstring[2] & 0x0F);
|
|
base_color_subblock2[2] |= base_color_subblock2[2] << 4;
|
|
}
|
|
uint32_t table_codeword1 = (bitstring[3] & 224) >> 5;
|
|
uint32_t table_codeword2 = (bitstring[3] & 28) >> 2;
|
|
uint32_t pixel_index_word = ((uint32_t)bitstring[4] << 24) | ((uint32_t)bitstring[5] << 16) | ((uint32_t)bitstring[6] << 8) | bitstring[7];
|
|
if (flipbit == 0)
|
|
{
|
|
ProcessPixelETC1(0, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(1, pixel_index_word, table_codeword1,base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(2, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(3, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(4, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(5, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(6, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(7, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(8, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(9, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(10, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(11, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(12, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(13, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(14, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(15, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
}
|
|
else
|
|
{
|
|
ProcessPixelETC1(0, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(1, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(2, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(3, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(4, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(5, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(6, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(7, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(8, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(9, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(10, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(11, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(12, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(13, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC1(14, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC1(15, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
}
|
|
return true;
|
|
}
|
|
|
|
static const int etc2_distance_table[8] = { 3, 6, 11, 16, 23, 32, 41, 64 };
|
|
|
|
static void ProcessBlockETC2TOrHMode(const uint8_t * DETEX_RESTRICT bitstring, int mode, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int base_color1_R, base_color1_G, base_color1_B;
|
|
int base_color2_R, base_color2_G, base_color2_B;
|
|
int paint_color_R[4], paint_color_G[4], paint_color_B[4];
|
|
int distance;
|
|
if (mode == DETEX_MODE_MASK_ETC_T)
|
|
{
|
|
// T mode.
|
|
base_color1_R = ((bitstring[0] & 0x18) >> 1) | (bitstring[0] & 0x3);
|
|
base_color1_R |= base_color1_R << 4;
|
|
base_color1_G = bitstring[1] & 0xF0;
|
|
base_color1_G |= base_color1_G >> 4;
|
|
base_color1_B = bitstring[1] & 0x0F;
|
|
base_color1_B |= base_color1_B << 4;
|
|
base_color2_R = bitstring[2] & 0xF0;
|
|
base_color2_R |= base_color2_R >> 4;
|
|
base_color2_G = bitstring[2] & 0x0F;
|
|
base_color2_G |= base_color2_G << 4;
|
|
base_color2_B = bitstring[3] & 0xF0;
|
|
base_color2_B |= base_color2_B >> 4;
|
|
// index = (da << 1) | db
|
|
distance = etc2_distance_table[((bitstring[3] & 0x0C) >> 1) | (bitstring[3] & 0x1)];
|
|
paint_color_R[0] = base_color1_R;
|
|
paint_color_G[0] = base_color1_G;
|
|
paint_color_B[0] = base_color1_B;
|
|
paint_color_R[2] = base_color2_R;
|
|
paint_color_G[2] = base_color2_G;
|
|
paint_color_B[2] = base_color2_B;
|
|
paint_color_R[1] = detexClamp0To255(base_color2_R + distance);
|
|
paint_color_G[1] = detexClamp0To255(base_color2_G + distance);
|
|
paint_color_B[1] = detexClamp0To255(base_color2_B + distance);
|
|
paint_color_R[3] = detexClamp0To255(base_color2_R - distance);
|
|
paint_color_G[3] = detexClamp0To255(base_color2_G - distance);
|
|
paint_color_B[3] = detexClamp0To255(base_color2_B - distance);
|
|
}
|
|
else
|
|
{
|
|
// H mode.
|
|
base_color1_R = (bitstring[0] & 0x78) >> 3;
|
|
base_color1_R |= base_color1_R << 4;
|
|
base_color1_G = ((bitstring[0] & 0x07) << 1) | ((bitstring[1] & 0x10) >> 4);
|
|
base_color1_G |= base_color1_G << 4;
|
|
base_color1_B = (bitstring[1] & 0x08) | ((bitstring[1] & 0x03) << 1) | ((bitstring[2] & 0x80) >> 7);
|
|
base_color1_B |= base_color1_B << 4;
|
|
base_color2_R = (bitstring[2] & 0x78) >> 3;
|
|
base_color2_R |= base_color2_R << 4;
|
|
base_color2_G = ((bitstring[2] & 0x07) << 1) | ((bitstring[3] & 0x80) >> 7);
|
|
base_color2_G |= base_color2_G << 4;
|
|
base_color2_B = (bitstring[3] & 0x78) >> 3;
|
|
base_color2_B |= base_color2_B << 4;
|
|
// da is most significant bit, db is middle bit, least significant bit is
|
|
// (base_color1 value >= base_color2 value).
|
|
int base_color1_value = (base_color1_R << 16) + (base_color1_G << 8) + base_color1_B;
|
|
int base_color2_value = (base_color2_R << 16) + (base_color2_G << 8) + base_color2_B;
|
|
int bit;
|
|
if (base_color1_value >= base_color2_value)
|
|
bit = 1;
|
|
else
|
|
bit = 0;
|
|
distance = etc2_distance_table[(bitstring[3] & 0x04) | ((bitstring[3] & 0x01) << 1) | bit];
|
|
paint_color_R[0] = detexClamp0To255(base_color1_R + distance);
|
|
paint_color_G[0] = detexClamp0To255(base_color1_G + distance);
|
|
paint_color_B[0] = detexClamp0To255(base_color1_B + distance);
|
|
paint_color_R[1] = detexClamp0To255(base_color1_R - distance);
|
|
paint_color_G[1] = detexClamp0To255(base_color1_G - distance);
|
|
paint_color_B[1] = detexClamp0To255(base_color1_B - distance);
|
|
paint_color_R[2] = detexClamp0To255(base_color2_R + distance);
|
|
paint_color_G[2] = detexClamp0To255(base_color2_G + distance);
|
|
paint_color_B[2] = detexClamp0To255(base_color2_B + distance);
|
|
paint_color_R[3] = detexClamp0To255(base_color2_R - distance);
|
|
paint_color_G[3] = detexClamp0To255(base_color2_G - distance);
|
|
paint_color_B[3] = detexClamp0To255(base_color2_B - distance);
|
|
}
|
|
uint32_t pixel_index_word = ((uint32_t)bitstring[4] << 24) | ((uint32_t)bitstring[5] << 16) | ((uint32_t)bitstring[6] << 8) | bitstring[7];
|
|
uint32_t *buffer = (uint32_t *)pixel_buffer;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel_index = ((pixel_index_word & (1 << i)) >> i) | ((pixel_index_word & (0x10000 << i)) >> (16 + i - 1));
|
|
int r = paint_color_R[pixel_index];
|
|
int g = paint_color_G[pixel_index];
|
|
int b = paint_color_B[pixel_index];
|
|
buffer[(i & 3) * 4 + ((i & 12) >> 2)] = detexPack32RGB8Alpha0xFF(r, g, b);
|
|
}
|
|
}
|
|
|
|
static void ProcessBlockETC2PlanarMode(const uint8_t * DETEX_RESTRICT bitstring, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
// Each color O, H and V is in 6-7-6 format.
|
|
int RO = (bitstring[0] & 0x7E) >> 1;
|
|
int GO = ((bitstring[0] & 0x1) << 6) | ((bitstring[1] & 0x7E) >> 1);
|
|
int BO = ((bitstring[1] & 0x1) << 5) | (bitstring[2] & 0x18) | ((bitstring[2] & 0x03) << 1) | ((bitstring[3] & 0x80) >> 7);
|
|
int RH = ((bitstring[3] & 0x7C) >> 1) | (bitstring[3] & 0x1);
|
|
int GH = (bitstring[4] & 0xFE) >> 1;
|
|
int BH = ((bitstring[4] & 0x1) << 5) | ((bitstring[5] & 0xF8) >> 3);
|
|
int RV = ((bitstring[5] & 0x7) << 3) | ((bitstring[6] & 0xE0) >> 5);
|
|
int GV = ((bitstring[6] & 0x1F) << 2) | ((bitstring[7] & 0xC0) >> 6);
|
|
int BV = bitstring[7] & 0x3F;
|
|
RO = (RO << 2) | ((RO & 0x30) >> 4); // Replicate bits.
|
|
GO = (GO << 1) | ((GO & 0x40) >> 6);
|
|
BO = (BO << 2) | ((BO & 0x30) >> 4);
|
|
RH = (RH << 2) | ((RH & 0x30) >> 4);
|
|
GH = (GH << 1) | ((GH & 0x40) >> 6);
|
|
BH = (BH << 2) | ((BH & 0x30) >> 4);
|
|
RV = (RV << 2) | ((RV & 0x30) >> 4);
|
|
GV = (GV << 1) | ((GV & 0x40) >> 6);
|
|
BV = (BV << 2) | ((BV & 0x30) >> 4);
|
|
uint32_t *buffer = (uint32_t *)pixel_buffer;
|
|
for (int y = 0; y < 4; y++)
|
|
{
|
|
for (int x = 0; x < 4; x++)
|
|
{
|
|
int r = detexClamp0To255((x * (RH - RO) + y * (RV - RO) + 4 * RO + 2) >> 2);
|
|
int g = detexClamp0To255((x * (GH - GO) + y * (GV - GO) + 4 * GO + 2) >> 2);
|
|
int b = detexClamp0To255((x * (BH - BO) + y * (BV - BO) + 4 * BO + 2) >> 2);
|
|
buffer[y * 4 + x] = detexPack32RGB8Alpha0xFF(r, g, b);
|
|
}
|
|
}
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the ETC2 format. */
|
|
bool detexDecompressBlockETC2(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
// Figure out the mode.
|
|
if ((bitstring[3] & 2) == 0)
|
|
{
|
|
// Individual mode.
|
|
return detexDecompressBlockETC1(bitstring, mode_mask, flags, pixel_buffer);
|
|
}
|
|
if ((mode_mask & (~DETEX_MODE_MASK_ETC_INDIVIDUAL)) == 0)
|
|
return false;
|
|
int R = (bitstring[0] & 0xF8);
|
|
R += complement3bitshifted(bitstring[0] & 7);
|
|
int G = (bitstring[1] & 0xF8);
|
|
G += complement3bitshifted(bitstring[1] & 7);
|
|
int B = (bitstring[2] & 0xF8);
|
|
B += complement3bitshifted(bitstring[2] & 7);
|
|
if (R & 0xFF07)
|
|
{
|
|
// T mode.
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_T) == 0)
|
|
return false;
|
|
ProcessBlockETC2TOrHMode(bitstring, DETEX_MODE_MASK_ETC_T, pixel_buffer);
|
|
return true;
|
|
}
|
|
else if (G & 0xFF07)
|
|
{
|
|
// H mode.
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_H) == 0)
|
|
return false;
|
|
ProcessBlockETC2TOrHMode(bitstring, DETEX_MODE_MASK_ETC_H,
|
|
pixel_buffer);
|
|
return true;
|
|
}
|
|
else if (B & 0xFF07)
|
|
{
|
|
// Planar mode.
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_PLANAR) == 0)
|
|
return false;
|
|
ProcessBlockETC2PlanarMode(bitstring, pixel_buffer);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Differential mode.
|
|
return detexDecompressBlockETC1(bitstring, mode_mask, flags, pixel_buffer);
|
|
}
|
|
}
|
|
|
|
static const int punchthrough_modifier_table[8][4] = {
|
|
{ 0, 8, 0, -8 },
|
|
{ 0, 17, 0, -17 },
|
|
{ 0, 29, 0, -29 },
|
|
{ 0, 42, 0, -42 },
|
|
{ 0, 60, 0, -60 },
|
|
{ 0, 80, 0, -80 },
|
|
{ 0, 106, 0, -106 },
|
|
{ 0, 183, 0, -183 }
|
|
};
|
|
|
|
static const uint32_t punchthrough_mask_table[4] = { 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF };
|
|
|
|
static DETEX_INLINE_ONLY void ProcessPixelETC2Punchthrough(uint8_t i, uint32_t pixel_index_word, uint32_t table_codeword, int * DETEX_RESTRICT base_color_subblock, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int pixel_index = ((pixel_index_word & (1 << i)) >> i) | ((pixel_index_word & (0x10000 << i)) >> (16 + i - 1));
|
|
int r, g, b;
|
|
int modifier = punchthrough_modifier_table[table_codeword][pixel_index];
|
|
r = detexClamp0To255(base_color_subblock[0] + modifier);
|
|
g = detexClamp0To255(base_color_subblock[1] + modifier);
|
|
b = detexClamp0To255(base_color_subblock[2] + modifier);
|
|
uint32_t mask = punchthrough_mask_table[pixel_index];
|
|
uint32_t *buffer = (uint32_t *)pixel_buffer;
|
|
buffer[(i & 3) * 4 + ((i & 12) >> 2)] = detexPack32RGB8Alpha0xFF(r, g, b) & mask;
|
|
}
|
|
|
|
|
|
void ProcessBlockETC2PunchthroughDifferentialMode(const uint8_t * DETEX_RESTRICT bitstring, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int flipbit = bitstring[3] & 1;
|
|
int base_color_subblock1[3];
|
|
int base_color_subblock2[3];
|
|
base_color_subblock1[0] = (bitstring[0] & 0xF8);
|
|
base_color_subblock1[0] |= ((base_color_subblock1[0] & 224) >> 5);
|
|
base_color_subblock1[1] = (bitstring[1] & 0xF8);
|
|
base_color_subblock1[1] |= (base_color_subblock1[1] & 224) >> 5;
|
|
base_color_subblock1[2] = (bitstring[2] & 0xF8);
|
|
base_color_subblock1[2] |= (base_color_subblock1[2] & 224) >> 5;
|
|
base_color_subblock2[0] = (bitstring[0] & 0xF8); // 5 highest order bits.
|
|
base_color_subblock2[0] += complement3bitshifted(bitstring[0] & 7); // Add difference.
|
|
base_color_subblock2[0] |= (base_color_subblock2[0] & 224) >> 5; // Replicate.
|
|
base_color_subblock2[1] = (bitstring[1] & 0xF8);
|
|
base_color_subblock2[1] += complement3bitshifted(bitstring[1] & 7);
|
|
base_color_subblock2[1] |= (base_color_subblock2[1] & 224) >> 5;
|
|
base_color_subblock2[2] = (bitstring[2] & 0xF8);
|
|
base_color_subblock2[2] += complement3bitshifted(bitstring[2] & 7);
|
|
base_color_subblock2[2] |= (base_color_subblock2[2] & 224) >> 5;
|
|
uint32_t table_codeword1 = (bitstring[3] & 224) >> 5;
|
|
uint32_t table_codeword2 = (bitstring[3] & 28) >> 2;
|
|
uint32_t pixel_index_word = ((uint32_t)bitstring[4] << 24) | ((uint32_t)bitstring[5] << 16) | ((uint32_t)bitstring[6] << 8) | bitstring[7];
|
|
if (flipbit == 0)
|
|
{
|
|
ProcessPixelETC2Punchthrough(0, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(1, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(2, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(3, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(4, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(5, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(6, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(7, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(8, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(9, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(10, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(11, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(12, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(13, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(14, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(15, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
}
|
|
else
|
|
{
|
|
ProcessPixelETC2Punchthrough(0, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(1, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(2, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(3, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(4, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(5, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(6, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(7, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(8, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(9, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(10, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(11, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(12, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(13, pixel_index_word, table_codeword1, base_color_subblock1, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(14, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
ProcessPixelETC2Punchthrough(15, pixel_index_word, table_codeword2, base_color_subblock2, pixel_buffer);
|
|
}
|
|
}
|
|
|
|
static void ProcessBlockETC2PunchthroughTOrHMode(const uint8_t * DETEX_RESTRICT bitstring, int mode, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int base_color1_R, base_color1_G, base_color1_B;
|
|
int base_color2_R, base_color2_G, base_color2_B;
|
|
int paint_color_R[4], paint_color_G[4], paint_color_B[4];
|
|
int distance;
|
|
if (mode == DETEX_MODE_MASK_ETC_T)
|
|
{
|
|
// T mode.
|
|
base_color1_R = ((bitstring[0] & 0x18) >> 1) | (bitstring[0] & 0x3);
|
|
base_color1_R |= base_color1_R << 4;
|
|
base_color1_G = bitstring[1] & 0xF0;
|
|
base_color1_G |= base_color1_G >> 4;
|
|
base_color1_B = bitstring[1] & 0x0F;
|
|
base_color1_B |= base_color1_B << 4;
|
|
base_color2_R = bitstring[2] & 0xF0;
|
|
base_color2_R |= base_color2_R >> 4;
|
|
base_color2_G = bitstring[2] & 0x0F;
|
|
base_color2_G |= base_color2_G << 4;
|
|
base_color2_B = bitstring[3] & 0xF0;
|
|
base_color2_B |= base_color2_B >> 4;
|
|
// index = (da << 1) | db
|
|
distance = etc2_distance_table[((bitstring[3] & 0x0C) >> 1) | (bitstring[3] & 0x1)];
|
|
paint_color_R[0] = base_color1_R;
|
|
paint_color_G[0] = base_color1_G;
|
|
paint_color_B[0] = base_color1_B;
|
|
paint_color_R[2] = base_color2_R;
|
|
paint_color_G[2] = base_color2_G;
|
|
paint_color_B[2] = base_color2_B;
|
|
paint_color_R[1] = detexClamp0To255(base_color2_R + distance);
|
|
paint_color_G[1] = detexClamp0To255(base_color2_G + distance);
|
|
paint_color_B[1] = detexClamp0To255(base_color2_B + distance);
|
|
paint_color_R[3] = detexClamp0To255(base_color2_R - distance);
|
|
paint_color_G[3] = detexClamp0To255(base_color2_G - distance);
|
|
paint_color_B[3] = detexClamp0To255(base_color2_B - distance);
|
|
}
|
|
else
|
|
{
|
|
// H mode.
|
|
base_color1_R = (bitstring[0] & 0x78) >> 3;
|
|
base_color1_R |= base_color1_R << 4;
|
|
base_color1_G = ((bitstring[0] & 0x07) << 1) | ((bitstring[1] & 0x10) >> 4);
|
|
base_color1_G |= base_color1_G << 4;
|
|
base_color1_B = (bitstring[1] & 0x08) | ((bitstring[1] & 0x03) << 1) | ((bitstring[2] & 0x80) >> 7);
|
|
base_color1_B |= base_color1_B << 4;
|
|
base_color2_R = (bitstring[2] & 0x78) >> 3;
|
|
base_color2_R |= base_color2_R << 4;
|
|
base_color2_G = ((bitstring[2] & 0x07) << 1) | ((bitstring[3] & 0x80) >> 7);
|
|
base_color2_G |= base_color2_G << 4;
|
|
base_color2_B = (bitstring[3] & 0x78) >> 3;
|
|
base_color2_B |= base_color2_B << 4;
|
|
// da is most significant bit, db is middle bit, least significant bit is
|
|
// (base_color1 value >= base_color2 value).
|
|
int base_color1_value = (base_color1_R << 16) + (base_color1_G << 8) + base_color1_B;
|
|
int base_color2_value = (base_color2_R << 16) + (base_color2_G << 8) + base_color2_B;
|
|
int bit;
|
|
if (base_color1_value >= base_color2_value)
|
|
bit = 1;
|
|
else
|
|
bit = 0;
|
|
distance = etc2_distance_table[(bitstring[3] & 0x04) | ((bitstring[3] & 0x01) << 1) | bit];
|
|
paint_color_R[0] = detexClamp0To255(base_color1_R + distance);
|
|
paint_color_G[0] = detexClamp0To255(base_color1_G + distance);
|
|
paint_color_B[0] = detexClamp0To255(base_color1_B + distance);
|
|
paint_color_R[1] = detexClamp0To255(base_color1_R - distance);
|
|
paint_color_G[1] = detexClamp0To255(base_color1_G - distance);
|
|
paint_color_B[1] = detexClamp0To255(base_color1_B - distance);
|
|
paint_color_R[2] = detexClamp0To255(base_color2_R + distance);
|
|
paint_color_G[2] = detexClamp0To255(base_color2_G + distance);
|
|
paint_color_B[2] = detexClamp0To255(base_color2_B + distance);
|
|
paint_color_R[3] = detexClamp0To255(base_color2_R - distance);
|
|
paint_color_G[3] = detexClamp0To255(base_color2_G - distance);
|
|
paint_color_B[3] = detexClamp0To255(base_color2_B - distance);
|
|
}
|
|
uint32_t pixel_index_word = ((uint32_t)bitstring[4] << 24) | ((uint32_t)bitstring[5] << 16) | ((uint32_t)bitstring[6] << 8) | bitstring[7];
|
|
uint32_t *buffer = (uint32_t *)pixel_buffer;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel_index = ((pixel_index_word & (1 << i)) >> i) | ((pixel_index_word & (0x10000 << i)) >> (16 + i - 1));
|
|
int r = paint_color_R[pixel_index];
|
|
int g = paint_color_G[pixel_index];
|
|
int b = paint_color_B[pixel_index];
|
|
uint32_t mask = punchthrough_mask_table[pixel_index];
|
|
buffer[(i & 3) * 4 + ((i & 12) >> 2)] = (detexPack32RGB8Alpha0xFF(r, g, b)) & mask;
|
|
}
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the ETC2_PUNCHTROUGH format. */
|
|
bool detexDecompressBlockETC2_PUNCHTHROUGH(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int R = (bitstring[0] & 0xF8);
|
|
R += complement3bitshifted(bitstring[0] & 7);
|
|
int G = (bitstring[1] & 0xF8);
|
|
G += complement3bitshifted(bitstring[1] & 7);
|
|
int B = (bitstring[2] & 0xF8);
|
|
B += complement3bitshifted(bitstring[2] & 7);
|
|
int opaque = bitstring[3] & 2;
|
|
if (opaque && (flags & DETEX_DECOMPRESS_FLAG_NON_OPAQUE_ONLY))
|
|
return false;
|
|
if (!opaque && (flags & DETEX_DECOMPRESS_FLAG_OPAQUE_ONLY))
|
|
return false;
|
|
if (R & 0xFF07)
|
|
{
|
|
// T mode.
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_T) == 0)
|
|
return false;
|
|
if (opaque)
|
|
{
|
|
ProcessBlockETC2TOrHMode(bitstring, DETEX_MODE_MASK_ETC_T, pixel_buffer);
|
|
return true;
|
|
}
|
|
// T mode with punchthrough alpha.
|
|
ProcessBlockETC2PunchthroughTOrHMode(bitstring, DETEX_MODE_MASK_ETC_T, pixel_buffer);
|
|
return true;
|
|
}
|
|
else if (G & 0xFF07)
|
|
{
|
|
// H mode.
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_H) == 0)
|
|
return false;
|
|
if (opaque)
|
|
{
|
|
ProcessBlockETC2TOrHMode(bitstring, DETEX_MODE_MASK_ETC_H, pixel_buffer);
|
|
return true;
|
|
}
|
|
// H mode with punchthrough alpha.
|
|
ProcessBlockETC2PunchthroughTOrHMode(bitstring, DETEX_MODE_MASK_ETC_H, pixel_buffer);
|
|
return true;
|
|
}
|
|
else if (B & 0xFF07)
|
|
{
|
|
// Planar mode.
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_PLANAR) == 0)
|
|
return false;
|
|
// Opaque always set.
|
|
if (flags & DETEX_DECOMPRESS_FLAG_NON_OPAQUE_ONLY)
|
|
return false;
|
|
ProcessBlockETC2PlanarMode(bitstring, pixel_buffer);
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
// Differential mode.
|
|
if (opaque)
|
|
return detexDecompressBlockETC1(bitstring, mode_mask, flags, pixel_buffer);
|
|
// Differential mode with punchthrough alpha.
|
|
if ((mode_mask & DETEX_MODE_MASK_ETC_DIFFERENTIAL) == 0)
|
|
return false;
|
|
ProcessBlockETC2PunchthroughDifferentialMode(bitstring, pixel_buffer);
|
|
return true;
|
|
}
|
|
}
|
|
|
|
static const int8_t eac_modifier_table[16][8] = {
|
|
{ -3, -6, -9, -15, 2, 5, 8, 14 },
|
|
{ -3, -7, -10, -13, 2, 6, 9, 12 },
|
|
{ -2, -5, -8, -13, 1, 4, 7, 12 },
|
|
{ -2, -4, -6, -13, 1, 3, 5, 12 },
|
|
{ -3, -6, -8, -12, 2, 5, 7, 11 },
|
|
{ -3, -7, -9, -11, 2, 6, 8, 10 },
|
|
{ -4, -7, -8, -11, 3, 6, 7, 10 },
|
|
{ -3, -5, -8, -11, 2, 4, 7, 10 },
|
|
{ -2, -6, -8, -10, 1, 5, 7, 9 },
|
|
{ -2, -5, -8, -10, 1, 4, 7, 9 },
|
|
{ -2, -4, -8, -10, 1, 3, 7, 9 },
|
|
{ -2, -5, -7, -10, 1, 4, 6, 9 },
|
|
{ -3, -4, -7, -10, 2, 3, 6, 9 },
|
|
{ -1, -2, -3, -10, 0, 1, 2, 9 },
|
|
{ -4, -6, -8, -9, 3, 5, 7, 8 },
|
|
{ -3, -5, -7, -9, 2, 4, 6, 8 }
|
|
};
|
|
|
|
static DETEX_INLINE_ONLY int modifier_times_multiplier(int modifier, int multiplier)
|
|
{
|
|
return modifier * multiplier;
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY void ProcessPixelEAC(uint8_t i, uint64_t pixels, const int8_t * DETEX_RESTRICT _modifier_table, int base_codeword, int multiplier, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int modifier = _modifier_table[(pixels >> (45 - i * 3)) & 7];
|
|
pixel_buffer[((i & 3) * 4 + ((i & 12) >> 2)) * 4 + DETEX_PIXEL32_ALPHA_BYTE_OFFSET] = detexClamp0To255(base_codeword + modifier_times_multiplier(modifier, multiplier));
|
|
}
|
|
|
|
/** Decompress a 128-bit 4x4 pixel texture block compressed using the ETC2_EAC format. */
|
|
bool detexDecompressBlockETC2_EAC(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
bool r = detexDecompressBlockETC2(&bitstring[8], mode_mask, flags, pixel_buffer);
|
|
if (!r)
|
|
return false;
|
|
// Decode the alpha part.
|
|
int base_codeword = bitstring[0];
|
|
const int8_t *_modifier_table = eac_modifier_table[(bitstring[1] & 0x0F)];
|
|
int multiplier = (bitstring[1] & 0xF0) >> 4;
|
|
if (multiplier == 0 && (flags & DETEX_DECOMPRESS_FLAG_ENCODE))
|
|
// Not allowed in encoding. Decoder should handle it.
|
|
return false;
|
|
uint64_t pixels = ((uint64_t)bitstring[2] << 40) | ((uint64_t)bitstring[3] << 32) | ((uint64_t)bitstring[4] << 24) | ((uint64_t)bitstring[5] << 16) | ((uint64_t)bitstring[6] << 8) | bitstring[7];
|
|
ProcessPixelEAC(0, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(1, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(2, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(3, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(4, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(5, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(6, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(7, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(8, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(9, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(10, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(11, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(12, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(13, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(14, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
ProcessPixelEAC(15, pixels, _modifier_table, base_codeword, multiplier, pixel_buffer);
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
For each pixel, decode an 11-bit integer and store as follows:
|
|
If shift and offset are zero, store each value in consecutive 16 bit values in pixel_buffer.
|
|
If shift is one, store each value in consecutive 32-bit words in pixel_buffer; if offset
|
|
is zero, store it in the first 16 bits, if offset is one store it in the last 16 bits of each
|
|
32-bit word.
|
|
*/
|
|
static DETEX_INLINE_ONLY void DecodeBlockEAC11Bit(uint64_t qword, int shift, int offset, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
int base_codeword_times_8_plus_4 = ((qword & 0xFF00000000000000) >> (56 - 3)) | 0x4;
|
|
int modifier_index = (qword & 0x000F000000000000) >> 48;
|
|
const int8_t *_modifier_table = eac_modifier_table[modifier_index];
|
|
int multiplier_times_8 = (qword & 0x00F0000000000000) >> (52 - 3);
|
|
if (multiplier_times_8 == 0)
|
|
multiplier_times_8 = 1;
|
|
uint16_t *buffer = (uint16_t *)pixel_buffer;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel_index = (qword & (0x0000E00000000000 >> (i * 3))) >> (45 - i * 3);
|
|
int modifier = _modifier_table[pixel_index];
|
|
uint32_t value = clamp2047(base_codeword_times_8_plus_4 + modifier * multiplier_times_8);
|
|
buffer[(((i & 3) * 4 + ((i & 12) >> 2)) << shift) + offset] = (value << 5) | (value >> 6); // Replicate bits to 16-bit.
|
|
}
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using theEAC_R11 format. */
|
|
bool detexDecompressBlockEAC_R11(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
uint64_t qword = ((uint64_t)bitstring[0] << 56) | ((uint64_t)bitstring[1] << 48) | ((uint64_t)bitstring[2] << 40) | ((uint64_t)bitstring[3] << 32) | ((uint64_t)bitstring[4] << 24) | ((uint64_t)bitstring[5] << 16) | ((uint64_t)bitstring[6] << 8) | bitstring[7];
|
|
DecodeBlockEAC11Bit(qword, 0, 0, pixel_buffer);
|
|
return true;
|
|
}
|
|
|
|
/** Decompress a 128-bit 4x4 pixel texture block compressed using the EAC_RG11 format. */
|
|
bool detexDecompressBlockEAC_RG11(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
uint64_t red_qword = ((uint64_t)bitstring[0] << 56) | ((uint64_t)bitstring[1] << 48) | ((uint64_t)bitstring[2] << 40) | ((uint64_t)bitstring[3] << 32) | ((uint64_t)bitstring[4] << 24) | ((uint64_t)bitstring[5] << 16) | ((uint64_t)bitstring[6] << 8) | bitstring[7];
|
|
DecodeBlockEAC11Bit(red_qword, 1, 0, pixel_buffer);
|
|
uint64_t green_qword = ((uint64_t)bitstring[8] << 56) | ((uint64_t)bitstring[9] << 48) | ((uint64_t)bitstring[10] << 40) | ((uint64_t)bitstring[11] << 32) | ((uint64_t)bitstring[12] << 24) | ((uint64_t)bitstring[13] << 16) | ((uint64_t)bitstring[14] << 8) | bitstring[15];
|
|
DecodeBlockEAC11Bit(green_qword, 1, 1, pixel_buffer);
|
|
return true;
|
|
}
|
|
|
|
static DETEX_INLINE_ONLY uint32_t ReplicateSigned11BitsTo16Bits(int value)
|
|
{
|
|
if (value >= 0)
|
|
return (value << 5) | (value >> 5);
|
|
value = - value;
|
|
value = (value << 5) | (value >> 5);
|
|
return - value;
|
|
}
|
|
|
|
/**
|
|
For each pixel, decode an 11-bit signed integer and store as follows:
|
|
If shift and offset are zero, store each value in consecutive 16 bit values in pixel_buffer.
|
|
If shift is one, store each value in consecutive 32-bit words in pixel_buffer; if offset
|
|
is zero, store it in the first 16 bits, if offset is one store it in the last 16 bits of each
|
|
32-bit word.
|
|
*/
|
|
static DETEX_INLINE_ONLY bool DecodeBlockEACSigned11Bit(uint64_t qword, int shift, int offset, uint8_t *pixel_buffer)
|
|
{
|
|
int base_codeword = (int8_t)((qword & 0xFF00000000000000) >> 56); // Signed 8 bits.
|
|
if (base_codeword == - 128)
|
|
// Not allowed in encoding. Decoder should handle it but we don't do that yet.
|
|
return false;
|
|
int base_codeword_times_8 = base_codeword << 3; // Arithmetic shift.
|
|
int modifier_index = (qword & 0x000F000000000000) >> 48;
|
|
const int8_t *_modifier_table = eac_modifier_table[modifier_index];
|
|
int multiplier_times_8 = (qword & 0x00F0000000000000) >> (52 - 3);
|
|
if (multiplier_times_8 == 0)
|
|
multiplier_times_8 = 1;
|
|
uint16_t *buffer = (uint16_t *)pixel_buffer;
|
|
for (int i = 0; i < 16; i++)
|
|
{
|
|
int pixel_index = (qword & (0x0000E00000000000 >> (i * 3))) >> (45 - i * 3);
|
|
int modifier = _modifier_table[pixel_index];
|
|
int value = clamp1023_signed(base_codeword_times_8 + modifier * multiplier_times_8);
|
|
uint32_t bits = ReplicateSigned11BitsTo16Bits(value);
|
|
buffer[(((i & 3) * 4 + ((i & 12) >> 2)) << shift) + offset] = bits;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/** Decompress a 64-bit 4x4 pixel texture block compressed using the EAC_SIGNED_R11 format. */
|
|
bool detexDecompressBlockEAC_SIGNED_R11(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
uint64_t qword = ((uint64_t)bitstring[0] << 56) | ((uint64_t)bitstring[1] << 48) | ((uint64_t)bitstring[2] << 40) | ((uint64_t)bitstring[3] << 32) | ((uint64_t)bitstring[4] << 24) | ((uint64_t)bitstring[5] << 16) | ((uint64_t)bitstring[6] << 8) | bitstring[7];
|
|
return DecodeBlockEACSigned11Bit(qword, 0, 0, pixel_buffer);
|
|
}
|
|
|
|
/** Decompress a 128-bit 4x4 pixel texture block compressed using the EAC_SIGNED_RG11 format. */
|
|
bool detexDecompressBlockEAC_SIGNED_RG11(const uint8_t * DETEX_RESTRICT bitstring, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer)
|
|
{
|
|
uint64_t red_qword = ((uint64_t)bitstring[0] << 56) | ((uint64_t)bitstring[1] << 48) | ((uint64_t)bitstring[2] << 40) | ((uint64_t)bitstring[3] << 32) | ((uint64_t)bitstring[4] << 24) | ((uint64_t)bitstring[5] << 16) | ((uint64_t)bitstring[6] << 8) | bitstring[7];
|
|
int r = DecodeBlockEACSigned11Bit(red_qword, 1, 0, pixel_buffer);
|
|
if (!r)
|
|
return false;
|
|
uint64_t green_qword = ((uint64_t)bitstring[8] << 56) | ((uint64_t)bitstring[9] << 48) | ((uint64_t)bitstring[10] << 40) | ((uint64_t)bitstring[11] << 32) | ((uint64_t)bitstring[12] << 24) | ((uint64_t)bitstring[13] << 16) | ((uint64_t)bitstring[14] << 8) | bitstring[15];
|
|
return DecodeBlockEACSigned11Bit(green_qword, 1, 1, pixel_buffer);
|
|
}
|
|
|
|
static detexDecompressBlockFuncType decompress_function[] =
|
|
{
|
|
NULL,
|
|
detexDecompressBlockBC1,
|
|
detexDecompressBlockBC1A,
|
|
detexDecompressBlockBC2,
|
|
detexDecompressBlockBC3,
|
|
detexDecompressBlockRGTC1,
|
|
detexDecompressBlockSIGNED_RGTC1,
|
|
detexDecompressBlockRGTC2,
|
|
detexDecompressBlockSIGNED_RGTC2,
|
|
detexDecompressBlockBPTC_FLOAT,
|
|
detexDecompressBlockBPTC_SIGNED_FLOAT,
|
|
detexDecompressBlockBPTC,
|
|
detexDecompressBlockETC1,
|
|
detexDecompressBlockETC2,
|
|
detexDecompressBlockETC2_PUNCHTHROUGH,
|
|
detexDecompressBlockETC2_EAC,
|
|
detexDecompressBlockEAC_R11,
|
|
detexDecompressBlockEAC_SIGNED_R11,
|
|
detexDecompressBlockEAC_RG11,
|
|
detexDecompressBlockEAC_SIGNED_RG11,
|
|
};
|
|
|
|
/**
|
|
General block decompression function. Block is decompressed using the given
|
|
compressed format, and stored in the given pixel format. Returns true if
|
|
succesful.
|
|
*/
|
|
bool detexDecompressBlock(const uint8_t * DETEX_RESTRICT bitstring, uint32_t texture_format, uint32_t mode_mask, uint32_t flags, uint8_t * DETEX_RESTRICT pixel_buffer, uint32_t pixel_format)
|
|
{
|
|
uint8_t block_buffer[DETEX_MAX_BLOCK_SIZE];
|
|
uint32_t compressed_format = detexGetCompressedFormat(texture_format);
|
|
bool r = decompress_function[compressed_format](bitstring, mode_mask, flags,
|
|
block_buffer);
|
|
if (!r)
|
|
{
|
|
detexSetErrorMessage("detexDecompressBlock: Decompress function for format returned error");
|
|
return false;
|
|
}
|
|
/* Convert into desired pixel format. */
|
|
return detexConvertPixels(block_buffer, 16, detexGetPixelFormat(texture_format), pixel_buffer, pixel_format);
|
|
}
|
|
|
|
// Look-up texture file info for KTX file format based on GL format parameters.
|
|
const detexTextureFileInfo *detexLookupKTXFileInfo(int gl_internal_format)
|
|
{
|
|
for (int i = 0; i < DETEX_NU_TEXTURE_INFO_ENTRIES; i++)
|
|
{
|
|
if (texture_info[i].gl_internal_format == gl_internal_format)
|
|
{
|
|
return &texture_info[i];
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*
|
|
* Decode texture function (linear). Decode an entire texture into a single
|
|
* image buffer, with pixels stored row-by-row, converting into the given pixel
|
|
* format.
|
|
*/
|
|
bool detexDecompressTextureLinear(const FDetexTexture *texture, uint8_t *pixel_buffer, uint32_t pixel_format)
|
|
{
|
|
uint8_t block_buffer[DETEX_MAX_BLOCK_SIZE];
|
|
|
|
const uint8_t *data = texture->data;
|
|
int pixel_size = detexGetPixelSize(pixel_format);
|
|
bool result = true;
|
|
for (int y = 0; y < texture->height_in_blocks; y++)
|
|
{
|
|
int nu_rows;
|
|
if (y * 4 + 3 >= texture->height)
|
|
{
|
|
nu_rows = texture->height - y * 4;
|
|
}
|
|
else
|
|
{
|
|
nu_rows = 4;
|
|
}
|
|
for (int x = 0; x < texture->width_in_blocks; x++)
|
|
{
|
|
bool r = detexDecompressBlock(data, texture->format, DETEX_MODE_MASK_ALL, 0, block_buffer, pixel_format);
|
|
uint32_t block_size = detexGetPixelSize(pixel_format) * 16;
|
|
if (!r)
|
|
{
|
|
result = false;
|
|
memset(block_buffer, 0, block_size);
|
|
}
|
|
uint8_t *pixelp = pixel_buffer + y * 4 * texture->width * pixel_size + x * 4 * pixel_size;
|
|
int nu_columns;
|
|
if (x * 4 + 3 >= texture->width)
|
|
{
|
|
nu_columns = texture->width - x * 4;
|
|
}
|
|
else
|
|
{
|
|
nu_columns = 4;
|
|
}
|
|
for (int row = 0; row < nu_rows; row++)
|
|
{
|
|
memcpy(pixelp + row * texture->width * pixel_size, block_buffer + row * 4 * pixel_size, nu_columns * pixel_size);
|
|
}
|
|
data += detexGetCompressedBlockSize(texture->format);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
bool DecompressTexture(uint8_t *data, const uint32_t SizeX, const uint32_t SizeY, uint32_t InternalFormat, uint8_t **decompressedData)
|
|
{
|
|
FDetexTexture dexTexture;
|
|
dexTexture.data = data;
|
|
dexTexture.width = SizeX;
|
|
dexTexture.height = SizeY;
|
|
const int32 BlockSizeX = 4;
|
|
const int32 BlockSizeY = 4;
|
|
dexTexture.width_in_blocks = FMath::Max(SizeX / BlockSizeX, (uint32_t)1);
|
|
dexTexture.height_in_blocks = FMath::Max(SizeY / BlockSizeY, (uint32_t)1);
|
|
const detexTextureFileInfo *DetexTFI = detexLookupKTXFileInfo(InternalFormat);
|
|
uint32_t pixel_format = detexGetPixelFormat(DetexTFI->texture_format);
|
|
dexTexture.format = DetexTFI->texture_format;
|
|
|
|
uint32_t decompressSize = SizeX * SizeY * detexGetPixelSize(pixel_format);
|
|
(*decompressedData) = (uint8_t *)malloc(decompressSize);
|
|
|
|
return detexDecompressTextureLinear(&dexTexture, *decompressedData, pixel_format);
|
|
}
|